Skip to content

Diag/25736 pan gesture trace - #36

Merged
sonora merged 30 commits into
sonora:hardy_25736from
osmandapp:diag/25736-pan-gesture-trace
Sep 6, 2026
Merged

Diag/25736 pan gesture trace#36
sonora merged 30 commits into
sonora:hardy_25736from
osmandapp:diag/25736-pan-gesture-trace

Conversation

@sonora

@sonora sonora commented Sep 6, 2026

Copy link
Copy Markdown
Owner

No description provided.

Chumva and others added 30 commits August 20, 2026 19:55
…eCantOpenDatabaseException in AnalyticsHelper
Removing the values-large widget text sizes (5ec248b) also shrank the
map scale label, which is not a panel widget and so cannot be enlarged
through the new widget appearance settings. On a 10" tablet the ruler bar
is still 180dp wide while its label dropped from 23sp to 15sp.

Give the ruler its own text size dimension and restore the tablet value.

#25374

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Keep the map scale text readable on tablets
Changing the group in a new point editor overwrites the picked color
with the group color, but colorSelected stayed true, so saving renewed
the last used time of a color that was never applied. Matches the iOS
behavior in OAEditPointViewController.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
OsmAndFormatter.formatValue() built a DecimalFormat, a DecimalFormatSymbols and a
MessageFormat on every single call, and createDecimalFormat() did the same for the
distance helpers. Constructing DecimalFormatSymbols resolves the locale currency
through ICU (Currency.getInstance -> ULocale.getKeywordValue -> LocaleIDParser), so
one formatted value costs about 0.45 ms on a mid-range device.

QuickSearchListAdapter.updateCompass() formats the distance of every visible row on
every compass update, from inside ListView.layoutChildren(). The resulting allocation
churn kept the collector busy and surfaced as a main-thread ANR in
art::gc::Heap::WaitForGcToCompleteLocked, currently the third most frequent
user-perceived stability issue on Play (223 affected users over 28 days).

Cache the formatters per thread instead: the cache key covers everything that changes
the instance configuration (pattern, locale, minimum fraction digits, thousands
grouping), so a cached instance is never reconfigured. DecimalFormat is mutable and not
thread safe, hence ThreadLocal.

Drop the MessageFormat wrapper as well - MessageFormat("{0}") with the DecimalFormat as
its only subformat just calls DecimalFormat.format(Object) on a boxed Float, which ends
in the same format(double) as calling the formatter directly.

Measured on an Android 15 arm64 emulator, 3000 calls: 1344 ms before, 130 ms after.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
hideParameterBar() called parameterBarLayout.setVisibility() directly,
crashing when the view was already null (e.g. map view torn down
before a pending raster-map-overlay dialog callback fires). The
sibling method hideTransparencyBar() had the same crash pattern and
was already fixed to use the null-safe AndroidUiHelper.updateVisibility()
helper in commit 54576ed (#23889); hideParameterBar() was missed.

Fixes #25862

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CaVbtbQJ3WWRrixYC7HscA
…n-maptransparencyhelperhideparameterbar-when-parameter-bar-layout-view-is-null

Fix NullPointerException in MapTransparencyHelper.hideParameterBar()
hideParameterBar() called parameterBarLayout.setVisibility() directly,
crashing when the view was already null (e.g. map view torn down
before a pending raster-map-overlay dialog callback fires). The
sibling method hideTransparencyBar() had the same crash pattern and
was already fixed to use the null-safe AndroidUiHelper.updateVisibility()
helper in commit 54576ed (#23889); hideParameterBar() was missed.

Fixes #25862

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CaVbtbQJ3WWRrixYC7HscA
(cherry picked from commit 2be4b0a)
Currently translated at 100.0% (5159 of 5159 strings)
Currently translated at 98.5% (5082 of 5159 strings)
Currently translated at 98.5% (5082 of 5159 strings)
Currently translated at 100.0% (5159 of 5159 strings)
Currently translated at 99.5% (5137 of 5159 strings)
Currently translated at 100.0% (5159 of 5159 strings)
Currently translated at 100.0% (5159 of 5159 strings)
Currently translated at 66.2% (3420 of 5159 strings)
Currently translated at 100.0% (5184 of 5184 strings)
Currently translated at 100.0% (5184 of 5184 strings)
Currently translated at 100.0% (5159 of 5159 strings)
Currently translated at 100.0% (5159 of 5159 strings)
…ph (#25815)

* Alternative routes for short city routes: plateau on the detailed graph

A route short enough that the two last-mile searches meet each other uses
no hub-graph edge at all, so the plateau method has nothing to build on and
returns nothing. Measured on a 4.3 km route in Amstelveen: the route is two
last-mile segments, 6 hub points are settled by both trees and all 6 fail
the plateau rule. Google offers three ways there.

The same plateau idea is applied one level down when the route has no hub
edges: a via node is a road point settled by both detailed trees, its cost
is f(v) + b(v) and its plateau is the stretch around it where that sum stays
constant. Expanding a candidate is a walk along parent links, so there is no
two-stage filter and no expansion budget - the candidates that survive the
plateau rule are assembled and checked on their real roads at once.

The trees come from a dedicated bidirectional Dijkstra: the last-mile trees
of the routing itself stop at the hub points around their own end and have
five road points in common. RoutingConfiguration.altHorizon, set only while
alternatives are searched, keeps that search from stopping at the first
meeting point and lets the two trees grow through each other.

ALT_MIN_DISTINCT_ABS (1500 m) becomes ALT_MIN_DISTINCT_FLOOR (300 m): as a
fixed requirement it was a third of a 4 km route while binding nothing above
7.5 km, where the relative rule takes over.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Update constant add test

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
…nd a fallback to the detailed graph (#25872)

Reported on a 1.7 km route in Kyiv (50.427112,30.470581 -> 50.416448,30.477190), which came
back with no alternative at all. Two separate reasons, both fixed here.

The route does use the hub graph (three segments), so the detailed method added in #25815 was
never tried - usesHubGraph() switched between the two methods instead of falling back. Only six
hub points end up settled by both trees on a route this short and none of them carries a plateau,
so the hub method returns nothing and there was nowhere else to look. The detailed search now
runs whenever the hub graph produced no alternative, bounded by ALT_DETAILED_MAX_COST: it grows
with the route (44 ms at 423 s of cost, 197 ms at 645 s, 274 ms at 978 s) and on a 140 km route
it costs 700 ms to find what is not there.

The other reason is that the only distinct way round here costs +49.6% - 2.5 km against 1.7 km -
and a purely relative limit rejects it. On a seven minute drive ALT_STRETCH allows three minutes,
and the next street rarely fits into that. ALT_STRETCH_ABS allows 180 s on top of the relative
limit, which is nothing on a route long enough for ALT_STRETCH to mean minutes.

Measured on a 12-route benchmark (Munich x4, Berlin, San Francisco x2, Paris x2, Tuscany,
Amstelveen, Kyiv): the alternatives offered are identical to the ones before this commit, and so
is the time spent on them - the 140 km route that finds nothing still spends 11 ms, not 700.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
@sonora
sonora merged commit 64b8d0d into sonora:hardy_25736 Sep 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.