## Problem
The Perfetto WASM decoder in `packages/native-devtools-android` returns
integer columns as `bigint` and only down-converts to `Number` when the
value is safe-integer-sized. From `readCell` in
`wasm-trace-processor.ts`:
```ts
if (typeof v === "bigint") {
// ... keep the bigint only for the rare unsafe-range value.
const n = Number(v);
return Number.isSafeInteger(n) ? n : v;
}
```
Native `CLOCK_MONOTONIC` timestamps exceed `2^53` ns after roughly 104
days of device/emulator uptime, so the absolute-time columns (`ts_ns`,
`first_ts_ns`, `last_ts_ns`) then arrive as `bigint` instead of
`number`. Meanwhile `getTraceStartNs()` already coerces
`trace_bounds.start_ts` to a plain `Number`.
The Android profiler pipeline then mixes the two — e.g. `row.first_ts_ns
- traceStartNs` and `Math.round((row.first_ts_ns - traceStartNs) /
1_000_000)` — which throws:
```
TypeError: Cannot mix BigInt and other types, use explicit conversions
```
The row TypeScript types annotate these columns as `number`, so the
compiler can't catch it, and `analyzeNativeProfilerAndroid`'s catch only
handles `TraceProcessorUnavailableError`. The result: a freshly captured
trace on a long-uptime device fails with a cryptic error instead of
producing a report.
## Repro
Feeding `start_ts` (Number-coerced) and
`ts_ns`/`first_ts_ns`/`last_ts_ns` as `bigint` greater than `2^53`
through `runAndroidProfilerPipeline` throws at `pipeline/index.ts:535`
(`cpuRowsToAggregatorRows`) / `:546` (`hangRowsToBottlenecks`). See the
new regression test, which fails before this change with the `TypeError`
above.
## Fix
Coerce the decoded absolute native-ns row fields with `Number(...)`
before any arithmetic that involves the already-Number `traceStartNs`
(matching what `getTraceStartNs` does). The downstream
`Math.round`/format logic is unchanged, and safe-range traces behave
identically. Sites fixed in
`packages/tool-server/src/utils/android-profiler/pipeline/index.ts`:
- `cpuRowsToAggregatorRows` — `first_ts_ns` / `last_ts_ns` offset
against `traceStartNs`.
- `hangRowsToBottlenecks` — `ts_ns` offset against `traceStartNs`, plus
`dur_ns` in `durationMs` and `endNs`.
- `renderHangStacksAndroid` (hang drill-down) — `ts_ns + dur_ns` and the
`durationMs` round.
Duration-only columns that never approach `2^53` ns (state/GC durations)
are left as-is; the GC fold path already normalises through
`toFiniteNumber`.
## Test
New `packages/tool-server/test/android-profiler-bigint.test.ts` drives
the real pipeline with `bigint` `ts_ns`/`first_ts_ns`/`last_ts_ns`
values greater than `2^53` (mocking only the WASM query layer, same
pattern as `pipeline-offset.test.ts`). It fails before the fix (the
documented `TypeError`) and passes after. Full tool-server suite: 1622
tests pass; `tsc --build` and `eslint` clean.