RE paperStrong evidence

Reverse engineering paper #4 — the fused position API we cannot reach

BYD's SDK defines a vehicle position with a heading in it. The contract is readable on this car; the implementation is not in this app.

BYD LabVerified 6 min read

readable in the SDK BYDAutoLocationDevice latitude 0–90N / S longitude 0–180E / W altitude ±8000 m8001 invalid orientation 0–359°360 invalid speed 0–240unit unknown satellites 0–50fix ok / fail behind the permission gate LocationManagerImpl “not impl” the contract is complete — nothing on this car ever returned one of its values

Our own app. Sealion 7 Pilot is developed by BYD Lab. It is held to the same standards as every other app on this site — read with that in mind.

Tested on

Vehicle
BYD Sealion 7 · Morocco
Head-unit version
51.1.4.2606220.1
Android
11
Verified

There is no heading anywhere on the vehicle bus (paper #3) — and yet the vehicle SDK on this car defines a position record with a heading field in it. This paper is about the gap between those two sentences.

Question#

Can an app on an export Sealion 7 actually obtain BYD’s vehicle-fused position — latitude, longitude, orientation, speed — through BYDAutoLocationDevice?

Environment#

Read-only decompile with jadx 1.5.5 of the 277-class android.hardware.bydauto.* SDK bundled inside BydSpotifyMusic.apk (com.telenav.scoutivi.spotify.byd), pulled off the unit. Everything below comes from that SDK’s classes and constants. Nothing was exercised: no device instance was constructed on the car, no listener was registered, and no value was ever received.

Observation#

The SDK’s device catalogue contains android.hardware.bydauto.location.BYDAutoLocationDevice, device type 1017. Its constants define a complete vehicle-side location record, and the record is not shaped like an Android Location.

Field Range Notes
Latitude 0–90 carried with a hemisphere type — LOCATION_LATITUDE_TYPE_NORTH / LOCATION_LATITUDE_TYPE_SOUTH
Longitude 0–180 carried with an EAST / WEST type
Altitude ±8000 m 8001 = invalid
LOCATION_ORIENTATION 0–359° 360 = invalid; a vehicle-provided heading
GPS speed 0–240 unit not confirmed by us
Visible satellites 0–50
Fix status — LOCATION_FIXPOSITION_SUCCESS / FAIL

Magnitude plus a hemisphere constant is the raw NMEA geodetic form, not the signed degrees an Android Location carries.

Delivery is push, not poll: registerListener(AbsBYDAutoLocationListener), with updates arriving on onDataEventChanged(...). The listener also carries onLocUseChange() and getLocUsePackageName() — the device reports who is currently using location, which is a platform-level concern, not an app-level one. The whole thing is permission-gated behind android.permission.BYDAUTO_LOCATION_GET, BYDAUTO_LOCATION_SET and BYDAUTO_LOCATION_COMMON.

Then there is the catch. In this app’s build, the concrete implementation sitting next to the device class — location/tsimpl/LocationManagerImpl — is a stub. It returns “not impl”, it is permission-guarded, and it reports an empty feature list.

Evidence#

Interpretation#

The contract and the implementation are in two different places, and only one of them is in front of us.

What we have is a complete, readable API definition for a vehicle-fused position that includes a heading — the same shape the domestic OneCore engine consumed on the cars that ship it (paper #1 records that stack, and it was not re-verified). The geodetic form and the satellite count point at a GNSS receiver on the vehicle side rather than at Android’s; the research record places that source at the vehicle’s own GNSS and dead-reckoning path. We did not verify where the data originates.

What we do not have is anything that answers. The stub in this app’s copy means the real implementation lives elsewhere — over binder, in the platform BYD/Car service, behind the BYDAUTO permissions. That is an inference from the stub’s shape, not something we observed: we never enumerated the platform service, never held the permissions, and never called the device.

So this does not mean the API is absent from the car, and it does not mean the permissions are unobtainable. It means that from where we stood — a normal, sideloaded, non-platform-signed app — nothing on this unit was shown to hand back a single one of these values.

Read against paper #3, it sharpens the picture rather than contradicting it. The car very likely computes a fused heading somewhere. It just does not publish it on the vehicle bus, and the one interface that would expose it is not implemented in anything we can read.

Result#

Strong: the contract for a vehicle-fused position with heading exists and is fully readable on this unit; the only copy of the implementation we could read is a stub, behind a permission gate a normal app does not pass, and we never observed the device return a value.

Two consequences for anyone building on this car:

  • Treat BYDAutoLocationDevice as a capability to probe for, behind a feature check that fails closed — never as something a feature depends on. A heading source that has never produced a number is not a heading source.
  • If you need heading today, it comes from GNSS course and the on-board IMU, not from the vehicle. Sealion 7 Pilot did not adopt this device for exactly that reason: out of scope, and not reachable without the BYDAUTO permissions.

Limitations#

Nothing here was exercised. That is the most important limitation and it applies to every claim in the paper: no BYDAutoLocationDevice was constructed, no AbsBYDAutoLocationListener was registered, no permission grant was attempted or observed to succeed or fail, and no field of the record was ever populated with a real number. This is a paper about a contract, read out of a decompiler.

We read one copy of the SDK — the one bundled inside the Scout app on this unit. Another app’s copy, a newer SDK, or the platform’s own framework classes may differ, and the stub is a property of this build, not a property of the platform.

We did not confirm that a platform-side implementation exists or is running on this car. The binder service that would host it was never enumerated.

We did not establish what LOCATION_ORIENTATION actually measures. The constant gives a range, not a definition: whether it is heading or course over ground, and whether it references true or magnetic north, is unknown. The same goes for units and scaling across the record — the 0–240 speed range in particular has no unit we can vouch for.

Sealion 7 Pilot declares BYDAUTO_LOCATION_COMMON and BYDAUTO_LOCATION_GET in its manifest and contains no reference to the device class at all. Declaring a permission is not holding one, and an app with no call site never finds out whether it would have been granted.

One car, one market, one head-unit build. Nothing here has been checked on another export market, another head-unit version, or a domestic unit — and the domestic comparison is a second-hand record of our own earlier work.

Reproduction#

Pull the app that carries the SDK, and decompile it on the host (our adb guide covers getting to the car):

Shell
adb shell pm path com.telenav.scoutivi.spotify.byd
adb pull <the path it prints> BydSpotifyMusic.apk
jadx -d out BydSpotifyMusic.apk

Then read, in this order: android/hardware/bydauto/location/BYDAutoLocationDevice, for the device type and the constant block; AbsBYDAutoLocationListener beside it, for the callback surface; and location/tsimpl/LocationManagerImpl, for the state of the implementation in this build. Read the tsimpl class in full rather than grepping — the finding there is that it does nothing, and doing nothing does not match a pattern.

The permission family is visible from the device:

Shell
adb shell pm list permissions -g -d | grep -i bydauto_location

The step we did not take, and the one that would settle this: from an app on the car holding the BYDAUTO location permissions, obtain a BYDAutoLocationDevice, register an AbsBYDAutoLocationListener, and watch whether onDataEventChanged ever fires. Whatever comes back — a security exception, silence, or a record — is a better answer than this paper has.