# ACR and telemetry components in LG webOS 3.5
## Scope and method
Subject is an extracted root filesystem from an LG TV, model 43UJ634V of year 2017, webOS 3.5. Service
country NL, firmware 06.10.75 (`mnt/lg/cmn_data/acr/data/firmware_version`).
All binaries are stripped ARM32 ELF. The analysis below is based on `strings` output,
package manifests under `usr/lib/opkg/info/`, configuration files, Luna service role and
activity definitions, and QML/JS application source that ships uncompiled. Where a claim
describes runtime behaviour, it is inferred from symbol names, format strings and Luna
method names rather than observed execution. Claims about state (opt-in flags, cached
files) come from files present in the dump and are direct evidence.
`old_root/` and `var/palm/jail/com.webos.app.browser/` are duplicate views of the same
tree and were excluded from path listings.
---
## 1. ACR: `acr2` and the Alphonso SDK
### Files
| Path | Description |
| --- | --- |
| `usr/sbin/acr2` | ACR daemon, registers Luna name `com.webos.service.acr`. Package `acr2 1.0.0-16.drd4tv.21-r2` |
| `usr/lib/libas.so.3.0.94` | Alphonso ACR SDK, 2.1 MB. Build paths retained: `/mnt/alpha/acr-sdk/sdk-build/git-lg-webos-3.5/acr-sdk/` |
| `usr/lib/libalphonsosolution.so.1.0.0` | LG shim between `acr2` and `libas.so`. Log prefix `LGASAPI` |
| `usr/lib/libsambasolution.so.1.0.0` | Second ACR vendor implementation, Samba TV. Not selected in this configuration |
| `usr/share/acr/acr.a.2.1.4.db.zero.mp3` | Audio reference file used by the SDK, 295 KB |
| `etc/palm/activities/com.webos.service.acr/activity-com.webos.service.acr.start.json` | Boot activity |
| `usr/share/dbus-1/system-services/com.webos.service.acr.service` | D-Bus activation, `Exec=/usr/sbin/acr2` |
| `usr/share/ls2/roles/pub/com.webos.service.acr.json` | Luna role, `inbound: ["*"]`, `outbound: ["*"]` |
`acr2` depends on `libas3.0.94 (>= 3.5.0-12)` per its opkg control file, so the Alphonso
SDK is a hard dependency of the shipped package, not an optional download.
### Startup
The boot activity subscribes to `luna://com.webos.bootManager/getBootStatus` and fires
`luna://com.webos.service.acr/startAcr` with `{"reason":"normal"}` when the signal
`rest-boot-done` becomes true. The service therefore starts on every boot regardless of
user interaction.
### Runtime configuration
`acr2` reads `/tmp/acr.xml`, whose location is pinned by
`mnt/lg/cmn_data/acr/data/config_file_path`. The file is not part of the firmware image;
it is downloaded by `usr/sbin/sdx` (see section 7). The copy captured in this dump:
```xml
```
The server has ACR enabled for this model and country (`ACR_On="true"`,
`send_data="true"`). Whether it runs is then gated on user consent, covered in section 8.
### What is captured
Audio only, in this configuration. `acr2` contains `DILE_AUDIO_PCM_RegSendPCMCallback`,
`DILE_AUDIO_PCM_StartUpload` and `DILE_AUDIO_PCM_StopUpload`, taking 100 ms windows of
48 kHz stereo PCM16 from ALSA device `dsnoop:0,12`. Fingerprinting happens inside
`libas.so`; raw audio is not sent.
A video path exists and is disabled here. `acr2` carries a `capture::VideoCapture` class,
`CAPTURE_LOCATION_SOURCE` / `CAPTURE_LOCATION_DISPLAY` modes, an `ImageConverter`, and
`CAPTURE_AcquireVtResouce` / `CAPTURE_CreateContext` calls. The config permits 2160p
capture on both broadcast and external inputs.
`capture_method="SOURCE"` means the tap is placed at the input source rather than the
final display composite, so overlays and OSD are excluded from what is fingerprinted.
### Wi-Fi scanning for location
Separate from audio fingerprinting, `acr2` enumerates surrounding wireless networks and
forwards them to Alphonso. The daemon contains a `core::WifiInterface` class that calls
`luna://com.webos.service.wifi/findnetworks` and parses `bssid` and `mac_address` out of
the reply (`[WifiInterface] get network_infos[%s]`). The shim exports this as
`LGASAPI::updateWifiScanInfo/solution:%s/nerwork_info:%s/result:%d` (typo in original).
Inside `libas.so` the corresponding handling is `AS_CLIENT_UPDATE_WIFI_SCAN_INFO`, with
`enable_wifi_scan` as a server-controlled toggle (`Recvd enable_wifi_scan:`,
`Wifi Scanning Start`, `Wifi Scanning Stop`, `Wifi Scanning disabled`), a
`wifiScanJsonOutput:` serialiser, and the fields `wifi_access_points`, `latitude`,
`longitude`.
Nearby BSSIDs resolve to a street-level position through any commercial AP geolocation
database. This is a location channel independent of the `zipcode` value that the SDK
also submits.
### Alphonso backends and API surface
Hostnames in `libas.so.3.0.94`: `prov-lg.alphonso.tv` (provisioning),
`eulacheck.alphonso.tv`.
Request paths:
```
/audio/fingerprint /user /user/location
/user/lookups /user/timed-lookups /user/appsource
/recommendation /recommendation/info /bl/config
/device/config /device/clock /countryList
/latestVersion /log/tar /sdk_debug/stats
```
Query parameters: `alp_uid`, `device_id`, `api_key`, `api_version_major`,
`api_version_minor`, `app_name`, `app_version_code`, `app_version_name`, `country`,
`zipcode`, `ipaddr`, `os_version`, `status`, `current_version`.
Client source files named in the binary indicate the feature set:
`ProvClient`, `UserRegClient`, `EULAClient`, `EULACountryListClient`, `LocationClient`,
`OTTRecmClient`, `OTTRecmFeedbackClient`, `RecmsPollClient`, `RecmUpdateParamsClient`,
`BusinessLogicServerClient`, `ASResultsLookupClient`, `SendBulkLogsClient`,
`ASClockSkewClient`, `MicReaderBufferCB`, `LocationServiceBufferCB`.
`MicReaderBufferCB` and `AudioReader.cpp` are SDK-generic (Alphonso ships the same SDK
for phones). On this platform the audio source is the PCM tap described above, not a
microphone.
### Samba TV as alternative vendor
`libsambasolution.so.1.0.0` is a complete second implementation, selected by setting
`ACRSolution="SAMBATV"` in the config. It carries its own libcurl HTTP client
(`network::HttpClient`, `HttpRequestCurl`), calls `acr_samba_initialize` and
`samba_acr_set_signature`, writes `/tmp/samba.log`, and reads a debug flag from
`/var/luna/preferences/debug_acr_libs`. Its callbacks carry `content_id`,
`ext_content_id`, `ext_source_id`, `title` and `payload`, and it can launch an overlay
application (`event : LAUNCH_ACR_APP (app_id(%s))`) and receive a viewer age
(`event : SET_APPLICATION AGE(%d)`).
The vendor is therefore switchable by server-side configuration without a firmware
update, since the config file is downloaded.
### Presentation applications
Six hidden web applications render whatever a fingerprint match returns, on top of live
video. All are `"visible": false`, `"class": {"hidden": true}`, `"transparent": true`,
and titled `LivePlus`.
| Application | Window group owner |
| --- | --- |
| `com.webos.app.acroverlay` | `com.webos.app.livetv` |
| `com.webos.app.acrcomponent` | `com.webos.app.externalinput.component` |
| `com.webos.app.acrhdmi1` .. `acrhdmi4` | the four HDMI input applications |
Each `index.html` sets an empty input region and `KeyMaskNone`, then loads a remote URL
into an iframe (`present_frm.html`). Teardown calls
`luna://com.webos.service.acr/setVideoPig` to shrink the video window and
`luna://com.webos.service.acr/closedApplication`.
Per-HDMI-port instances mean recognition applies to attached devices, including set-top
boxes, consoles and streaming sticks, not only to the tuner.
### Luna API exposed by `acr2`
`startAcr`, `setACRsetting`, `getACRstatus`, `getACRAppStatus`, `getACRLaunchFlag`,
`getACRSolutionStatus`, `getAudioCaptureStatus`, `getVideoCaptureStatus`,
`getCaptureCondition`, `getCaptureSpeed`, `setCaptureSpeed`, `setVideoPig`,
`setForceAliveTime`, `setSessionControl`, `setCloseCaption`, `closedApplication`,
`sendLChannelInfo`, `sendMessage`, `getCurrentChannelInfo`, `getProductVersion`.
The daemon also subscribes to tuner and power state:
`com.webos.service.tv.broadcast/getCurrentChannel`, `.../getChannelState`,
`com.webos.service.tv.channel/getLastChannelId`,
`com.webos.service.tv.externaldevice/input/getSignalState`,
`com.webos.service.tv.display/getCurrentVideo`, `.../getScreenStatus`,
`com.webos.service.tvpower/power/getPowerState`,
`com.webos.service.tv.dvr/play/isDelayedPlaying`, `.../play/isPauseOnLive`,
`.../record/isTimeshiftBuffering`.
Channel identity, input, DVR and timeshift state accompany each recognition attempt via
`LGASAPI::updateSource/solution/provider/input/channel_name/channel_number/major_number/
minor_number/livetv/vod`.
### State directory
`mnt/lg/cmn_data/acr/` (mirrored at `mnt/lg/user/acr/` and `mnt/lg/flash/data/acr/`):
```
data/config_file_path -> /tmp/acr.xml
data/service_country -> NL
data/sdp_server -> Production
data/firmware_version -> 06.10.75
data/first_optout -> present
lib/ -> empty
alphonso/ -> reference mp3 + log4cplus.properties
```
Paths `acr2` also knows about but which are absent here: `data/optin`,
`data/eula_allowed`, `data/power_off_info`.
---
## 2. Advertising: `admanager`
`usr/sbin/admanager`, package `admanager 2.1.1-101.drd4tv.9-r7`, described in its control
file as "Advertisement Service Manager", source `git://wall.lge.com/service/admanager`.
Hostname compiled in: `info.lgsmartad.com`. Endpoints `/rest/json/v1.0/baseinfo`,
`/rest/json/v1.0/appinfo`, `/rest/json/v1.0/req`, `/rest/xml/v1.0/api/TNC?TNC=`.
Parameters: `app_id`, `down_app_id`, `width`, `height`, `roll_type`, `ifa`, `ifa_type`,
`lmt`, `opt_out`.
It implements the VAST/VPAID tracking vocabulary: `Click Tracking URL`,
`ClickThrough URL`, `ClickThrough ID`, `CompanionClickThrough`, `CompanionClickTracking`,
`ErrorTracker`, plus `=== Tracking Event List ===` and `=== Click Tracking Event List ===`
dump routines.
This component has run on the device. `mnt/lg/cmn_data/admanager/` contains:
- `cache/` with roughly fifty fetched creatives whose filenames encode their source URLs,
from `cdn-aas-campaigns.alphonso.tv/campaigns/images/...` and
`media.bidr.io/alphonso/...`. Several are Dutch-market LG campaigns
(`SmartTV_Netherlands_wedge`, `LG_Wedge_nl_1440x1080`).
- `cookie/ad_cookie`, a libcurl cookie jar for `nl.ad.lgsmartad.com` holding `JSESSIONID`
and the frequency-capping counters `ADSTIME`, `DayCuki0`, `CamDaily0`, `AdSlotDaily0`,
with expiry timestamps in 2026.
- `tmpData/baseInfo.tmp`, the cached slot manifest:
```json
{"advs":{"adServer":"https://nl.ad.lgsmartad.com",
"userAgent":"Mozilla/5.0 (LG smartTV)","sponsoredText":"Sponsored",
"adSlotList":{"adSlotSet":[
{"adSlotName":"Portal/Discovery@Main","adSlot":7689},
{"adSlotName":"Portal/Browser@Main","adSlot":8024},
{"adSlotName":"Portal/Wedge@Main","adSlot":10565},
{"adSlotName":"Portal/LGChannelPause@Main","adSlot":29088}]},
"cmpInfo":{"visibility":false}}}
```
The creative CDN being `alphonso.tv` links the ad delivery path to the same vendor that
supplies the ACR SDK, though the two components are separate processes and the ad slots
here are placements in LG's own UI (home row, browser, pause screen) rather than
ACR-triggered overlays.
Client applications: `com.webos.app.voice/qml/Service/AdManagerService.qml`,
`com.webos.app.searchanddiscovery/qml/Discovery/DiscoveryService.qml`.
Boot job `etc/init/admanager.conf` creates the cache directory at `init-boot-done`.
---
## 3. Channel-change reporting to IBS
`usr/palm/applications/com.webos.app.inputcommon/qml/Service/PersonalDataService.qml`
and `qml/Model/PersonalDataLogModel.qml`.
On channel change, and once three seconds after the channel list loads, the TV posts a
form body to `sdp/livetvwatch.json` on service `ibis_stat_secure`, which resolves to
`https://ibsstat.lgappstv.com/ibs/v2.8/`. Delivery is through
`luna://com.webos.service.sdx/send` with `REQ_SSL_POST_METHOD`.
Body, verbatim from the source:
```
chan_name, chan_code, prev_chan_code, channel_change,
device_src_idx (0 unknown / 1 TV / 2 STB),
dtv_standard_type (1 ATSC / 2 DVB / 3 ISDB),
accept_flag=1, zipcode, timezone, user_id
```
`user_id` is `deviceUniqueId`, obtained together with `watchFlag` from
`luna://com.webos.service.pbsw/getIbsHeaderData`. `usr/sbin/pbs` provides it
(`PBS_UTIL_GetDeviceUniqueId`, `MAIN_MANAGER_GetAuthWatchFlag`) and talks to
`ibs.lgappstv.com` and `ibsstat.lgappstv.com`.
Two gates apply. `watchFlag` must be true, and the server can switch reporting off by
returning `activation_flag != "ON"`. `_getEnableCountry()` restricts the feature to
`KOR`, `GBR`, `ESP`, `FRA`, `BRA`, `RUS`, `DEU`. This unit is NL, so the path is inactive
here. The `accept_flag=1` constant is hardcoded and does not consult `eulaStatus`; the
QML fetches `eulaStatus` but only via `getEula()`, which is not called on the send path.
---
## 4. Crash and analytics upload: `rdxd`
`usr/sbin/rdxd`, package version 3.3.0-172.drd4tv.7-r4, with `usr/sbin/rdx_reporter` and
helper scripts in `usr/share/rdxd/`. `etc/rdxd.conf` sets `AutoUpload=true`.
Three report classes are staged separately: `/tmp/rdxd/crash`, `/tmp/rdxd/analytics`,
`/tmp/rdxd/overview`, spooled through `/var/spool/rdxd/pending` to
`/var/spool/rdxd/uploaded`. Context is gathered by
`make_overview_head.sh`, `make_sdp_crash.sh`, `make_cloud_overview.sh`,
`prepare_cloud_crash.sh`, `filter.sh`, and can include `/var/log/messages` and kernel
logs (`make_kernel.sh`, `make_syslog.sh`, `make_sysinfo.sh`, `make_preboot.sh`).
Two egress paths exist.
**SDP.** `luna://com.palm.uploadd/upload`, with request headers supplied by
`luna://com.webos.service.sdx/getHttpHeaderForServiceRequest`. The endpoint table maps
service `rdx_secure` to `rdx2.lgtvsdp.com/v7.0/`.
**Sumo Logic.** `usr/share/rdxd/conf/cloud.json` holds three hardcoded HTTP collector
URLs on `collectors.sumologic.com/receiver/v1/http/`, with headers
`X-Sumo-Category: OS/webOS/{Crash,Analytics,Overview}` and
`X-Sumo-Name: %nduid%`. The device identifier substituted into the name is
`com.palm.properties.nduid`. Payloads are gzip or deflate encoded. The shipped file sets
`"general": {"enable": false}`; the runtime override location is
`/var/preferences/com.webos.rdxd/cloud.json`, which is not present in this dump.
`rdxd` checks `/var/luna/preferences/devmode_enabled` and suppresses upload when developer
mode is on, and queries `luna://com.webos.settingsservice/getSystemSettings` before
uploading. The `Analytics` category and `ANALYTICS_REPORT_CREATED` marker indicate the
channel carries more than crash dumps.
---
## 5. Remote diagnostics: `remotediag`
`usr/sbin/remotediag` registers `com.webos.service.remotediag` and reads `eulaStatus` and
`eulaInfoNetwork`, keyed on `remoteDiagAllowed`.
Server names: `rone-kic.lge.com`, `rone-eic.lge.com`, `rone-aic.lge.com`,
`rone-tv-kic.lge.com`, `rone-tv-eic.lge.com`, `rone-tv-aic.lge.com`,
`rone-tv-cic.lge.com` (KIC/EIC/AIC/CIC being LG's Korea, Europe, America and China
regional data centres). Also present are literal internal addresses
`165.244.62.249:6120`, `:6230`, `:6240` and `10.185.223.172:80`.
Authentication material: `usr/share/remotediag/device.pem`,
`usr/share/remotediag/server.pem`, with the key unwrapped through
`DILE_CRYPTO_ReadRemoteDiagSecret`.
Once connected it can call `luna://com.webos.audio/setVolume`, `setMuted`,
`luna://com.webos.applicationManager/launch` and
`luna://com.palm.systemservice/setPreferences`, so the channel is control as well as
telemetry. Logs are written to `mnt/lg/cmn_data/remotediag_*.log`.
`usr/sbin/remotelogger` and `usr/sbin/snaplog` are local log collectors with no HTTP
client linked.
---
## 6. Voice: `nlp` and `nlpmanager`
`usr/sbin/nlp` sends recognition traffic to LG's AI backends:
`he-eu-ai.lgthinq.com:443`, `he-us-ai.lgthinq.com:443`, `he-kr-ai.lgthinq.com:443`,
`he-ru-ai.lgthinq.com:443`, with QA variants, plus
`lgs2gb.lpoong.com`, `lgs2us.lpoong.com`, `lgs2kr.lpoong.com`, `lgs2mx.lpoong.com`,
`lgs2au.lpoong.com`. The target is injected per request through an `X-SDP-NLP-URL:` header.
`usr/sbin/nlpmanager` handles the SDP side: `/rest/sdp/v5.0/nlp/service`,
`/rest/sdp/v5.0/nlp/tvtips`, `/rest/sdp/v8.0/search/retrieval`,
`sdp/getNextNsEventList.json`, over service `ibis_secure`. It emits usage logs with
`ibis_valuelist`, `ibis_timezone` and `ibis_device_source_type` parameters. Pinned CA at
`usr/share/ca-certificates/sdp/sdp-ca.pem`.
Gated on `voiceAllowed` / `voice2Allowed`, both false here.
---
## 7. Platform transport: `sdx`
`usr/sbin/sdx` (`com.webos.service.sdx`) is the shared HTTP client for LG cloud services.
Applications do not open sockets themselves; they call `luna://com.webos.service.sdx/send`
with a `serviceName`, a relative `url`, a `methodType` and a body, and `sdx` resolves the
service name against the endpoint table.
`sdx` handles device authentication, EULA synchronisation, terms retrieval and withdrawal,
and it downloads the ACR configuration. Relevant symbols: `sdx::handler::ReqACRHandler`,
`sdx::handler::SDPACRHandle`, `RequestMessage::is_acr_version_check`,
`ACR_VERSION_CHECK`, `ACR_VERSION_DOWNLOAD`, `requestACRVersion`, `getACRPath`,
`_make_dir_acr`, `unmashalling_ACR`, target path `/tmp/acr.xml`, service name
`sdp_check_acr`. Device identity is `LGUDID`, hashed before transmission
(`hashed lgudid is NULL`, `idType is NOT LGUDID`).
The endpoint table is `mnt/lg/cmn_data/sdp/sdx/server_addr_version.conf`, mirrored at
`usr/palm/sdx/server_addr_version.conf`. Entries relevant to data collection:
| Service name | Host | Base path |
| --- | --- | --- |
| `sdp`, `sdp_devauth`, `sdp_terms`, `sdp_check_acr` | `lgtvsdp.com` | `rest/sdp/v8.0/` |
| `ibis`, `ibis_secure` | `ibs.lgappstv.com` | `ibs/v2.8/` |
| `ibis_stat_secure` | `ibsstat.lgappstv.com` | `ibs/v2.8/` |
| `rdx`, `rdx_secure` | `rdx2.lgtvsdp.com` | `/v7.0/` |
| `cdpbeacon_secure` | `cdpbeacon.lgtvcommon.com` | `api/v1/beacon/` |
| `cdp_service_secure` | `cdpsvc.lgtvcommon.com` | `api/v1.0/` |
| `recommend_secure` | `recommend.lgtvcommon.com` | `recommend/v1/` |
| `homeprv_secure` | `homeprv.lgtvcommon.com` | `homeprv/` |
| `nudge_secure` | `nudge.lgtvcommon.com` | `nudge/` |
| `wau_secure` | `wau.lgtvcommon.com` | `wau/v1.0/` |
| `cpv_secure` | `pnv.lgtvcommon.com` | `rest/csi/` |
| `iot`, `iot_push_secure` | `api.lgtviot.com`, `push.lgtviot.com` | `/v1.0/` |
| `voice_proxy_secure` | `netflixvoice.lgtvcommon.com` | `proxy/` |
The `cdpbeacon`, `cdpsvc`, `recommend`, `homeprv`, `nudge` and `wau` names have no
consumer anywhere in this firmware. They appear only in the table itself and in
`PersonalDataService.qml`'s neighbouring service list. On webOS 3.5 they are unused
declarations; they are the beacon and profile endpoints used by later firmware.
Other endpoints outside the SDP table:
- `usr/sbin/pushmanager`: `device.lgeapi.com`, `push.lgeapi.com`,
`push-sender.lgsmartplatform.com`, with `/device/1.0/device`,
`/device/1.0/devices/%s/authkey`, `/push/v1.0/receiver`,
`/push/v1.0/receiver/%s/status`. Staging and QA hostnames are present but commented in
the embedded default config.
- `etc/connman/main.conf`: connectivity probe at `http://lgtvonline.lge.com/` for both
IPv4 and IPv6.
- `mnt/lg/cmn_data/var/palm/data/com.webos.appInstallService/serverInfo`: app store
endpoints.
---
## 8. Consent state on this device
Everything relevant is switched off.
`var/luna/preferences/option`:
```
livePlus = "off"
```
`livePlus` is the settings key backing the "Live Plus" toggle, category `option`, defined
in `usr/palm/applications/com.palm.app.settings/app.js`. Its help text names ACR
explicitly:
> By turning Live Plus on, you are consenting to the collection of television viewing
> information by LG Electronics Inc. ("LGE") through ACR module, which may be shared
> anonymously with third parties to provide you with interactive services. We may also
> share aggregated anonymous information with third parties for marketing purposes.
`var/luna/preferences/general`:
```
adCookie = "off"
customizedAd = "off"
personalRecommend = {"changedByUser": false, "value": "off"}
```
`var/luna/preferences/eula`, `eulaStatus`:
```
acrAllowed false acrOnAllowed false
acrAdAllowed false acrGdprAllowed false
customAdAllowed false customadsAllowed false
cookiesAllowed false thirdPartySharingAllowed false
generalTermsAllowed false additionalDataAllowed false
remoteDiagAllowed false voiceAllowed false
voice2Allowed false chpAllowed false
takeOnAllowed false additional1..5Allowed false
networkAllowed true
```
All ten EULA documents in `eulaInfo.eulaList` show `accepted: false`
(`S_SVC`, `S_PRG`, `S_PRV`, `S_PRD`, `S_PRT`, `S_ADG`, `S_ADC`, `S_ADD`, `S_TAG`,
`S_TAD`).
`mnt/lg/cmn_data/sdp/sdx/eula.json` records one entry, `managementTypeCode: "X_INT"`,
`status: "W"` (withheld), `eulaChangeReason: "initialized"`.
Corroborating file state: `mnt/lg/cmn_data/acr/data/first_optout` exists and
`mnt/lg/cmn_data/acr/data/optin` does not, matching the config attribute
`should-send-first-optout="true"`, which instructs the client to transmit an explicit
opt-out signal once. `mnt/lg/cmn_data/acr/lib/` is empty.
The ad stack is the one component with evidence of past activity, in the form of cached
creatives and unexpired frequency-capping cookies for `nl.ad.lgsmartad.com`. The ad slots
concerned are placements in LG's own interface and are not conditioned on ACR.
Settings UI also disables the `livePlus` and `adCookie` toggles when
`enableHotelMode === "on"` or `supportBNO` is set.
---
## 9. Examined and excluded
`usr/bin/webos-statistics-manager` (`com.webos.statisticsManager`). Despite the name it
writes only to the local DB8 kind `com.webos.statisticsManager.appLaunchHistory:1`, whose
schema is `id`, `launchCount`, `lastLaunchTime`. Its stated purpose in the binary is
"Applaunch event history for preloading apps". No HTTP client is linked. Configuration in
`etc/palm/webos-statistics-manager-conf.json` seeds Netflix with a launch count of 50 to
bias preloading. It flushes on power-off via an activity.
`usr/sbin/prs` (Program Recommendation Service). Scores viewing history locally;
`mnt/lg/cmn_data/prs/prs_config.json` holds weights such as `favorite_program_weight` and
`recommend_history_update_period`. No `curl_easy_perform` reference. The database
`PRS_DB_FIRST_1.db` is zero bytes. It does set `"recmd_origin": "online"`, so it consumes
server-side recommendations even though it does not upload.
`usr/sbin/scd-service`, `usr/sbin/cbox`, `usr/sbin/snaplog`, `usr/sbin/crashd`,
`usr/sbin/faultmanager`, `usr/sbin/remotelogger`, `usr/sbin/rdx_reporter`: none link a
network client.
---
## 10. Summary of network-facing collection paths
| Component | Destination | Data | Active on this unit |
| --- | --- | --- | --- |
| `acr2` + `libas.so` | `prov-lg.alphonso.tv`, `eulacheck.alphonso.tv` | Audio fingerprints, channel and input identity, nearby Wi-Fi BSSIDs, zipcode, IP | No. `livePlus=off`, `acrAllowed=false`, `first_optout` written |
| `admanager` | `info.lgsmartad.com`, `nl.ad.lgsmartad.com` | Ad requests with `ifa` / `lmt` / `opt_out`, impression and click tracking | Has run. Cached creatives and live cookies present |
| `inputcommon` PersonalLog | `ibsstat.lgappstv.com` | Every channel change with previous channel, zipcode, timezone, device ID | No. Country gate excludes NL |
| `rdxd` | `rdx2.lgtvsdp.com`, `collectors.sumologic.com` | Crash dumps, system logs, "analytics" and "overview" reports keyed by nduid | Cloud path `enable: false`; spool empty |
| `remotediag` | `rone-*.lge.com` | Diagnostic session, plus remote control of volume and app launch | No. `remoteDiagAllowed=false` |
| `nlp` / `nlpmanager` | `*.lgthinq.com`, `*.lpoong.com`, `ibs.lgappstv.com` | Voice queries and usage logs | No. `voiceAllowed=false` |
| `pushmanager` | `push.lgeapi.com`, `device.lgeapi.com` | Device registration and push receipt | Registration is unconditional |
| `sdx` | `lgtvsdp.com` | Device auth, EULA sync, ACR config download | Yes. `/tmp/acr.xml` was fetched |
---
## 11. Limits of this analysis
No binary was disassembled. Control flow, and in particular the exact conditions under
which each consent flag is enforced, is inferred from strings and from the QML and JS
sources that ship readable. Two specific gaps:
- Whether `acr2` re-reads `eulaStatus` at runtime, or trusts the `send_data` attribute in
a config file it obtained over the network, is not resolvable from strings alone. The
daemon references both `eulaStatus`, `acrOnAllowed`, `acrAdAllowed` and a
`data/eula_allowed` file it did not create here.
- `/tmp/acr.xml` is server-supplied and mutable. `ACRSolution`, `send_data`,
`video capture` and the Alphonso `enable_wifi_scan` flag can all change without a
firmware update.
Confirming actual behaviour requires either disassembly of `acr2` and `libas.so.3.0.94`,
or network capture from a running device with `livePlus` toggled.