TV research¶
Findings about how LG's webOS works, kept so the same ground is not covered twice. Each entry names the TV and webOS version it was found on. For how Native Tv itself works, see IMPLEMENTATION.md.
HDMI CEC devices (G3, webOS 9.2.2)¶
com.webos.service.eim/getAllInputStatus returns CEC devices in each HDMI
input's subList, with id: SIMPLINK. HDMI 2 on an OLED55G36LA reported
STEREO 70s at depth 1 and PlayStation 5 at depth 2. Entries include
osdName, cecpDevType, vendorId, physicalAddress and uniqueId.
Non-SIMPLINK entries can describe universal-remote configuration instead.
On the same TV, unplugged HDMI 1 and HDMI 3 returned connected: true, but
hdmiPlugIn: false, hdmiSignalExist: false, lastUniqueId: -1 and empty
sublists. Where present, hdmiPlugIn takes precedence over connected for
plug detection. The device list does not report per-device power state.
The picture of an input behind Home (G3, webOS 9.2.2)¶
With a web app on screen, an HDMI input's receiver stays locked to its
source. /proc/lg/hdmi20/port0/status (HDMI 4) kept PHY Lock[1], Sig:
[3840]x[2160]@[23]Hz, Video Format[Y444], DeepColorMode[10BIT] and
cvi_vfreq[2400]; Sig's rate rounds down, cvi_vfreq is in hundredths of a
hertz. The same directory's pkt lists the last packet of each kind as bytes.
Its DRM entry (Dynamic Range and Mastering InfoFrame, header 0x87) had EOTF
0x02 (PQ) in the byte after the checksum; an input with nothing connected
reads all zeros. Switching to HDMI 4, videooutput's getStatus reported
hdrType: HDR10, EOTFtype: 2 and 24 Hz, matching both. When the same
source later went back to SDR, the DRM entry was all zeros again, the status
read Video Format[R444] and DeepColorMode[ 8BIT] (padded), and
videooutput reported hdrType: none. Whether Dolby HDR Info turns to 1 for
a Dolby Vision source over HDMI was not seen.
An app's video is gone once it stops, but while it plays videooutput's
getStatus names it on the MAIN sink with connectedSource: VDEC: Netflix
gave 3840x2160, frameRate: 23.9760246, hdrType: DolbyVision, and the
settings service read dimension: {input: 'default', dynamicRange:
'dolbyHdr'}, mode dolbyHdrCinemaBright. A subscription to getStatus
answers at once with the current state. YouTube's home page plays a preview
(854x480, 25 Hz) on the same sink.
settings/getSystemSettings keeps a picture mode for each input and dynamic
range, and reads another input's only when both are given:
dimension: {input: 'hdmi2'} answers no result from DB, {input: 'hdmi2',
dynamicRange: 'sdr'} answers. Inputs are hdmi1 to hdmi4, dtv, ip and
default; the four HDMI inputs had four different HDR modes. An app on screen
(YouTube) reads as input default. backlight is kept for each input and
picture mode, dimension: {input, pictureMode}, and adding dynamicRange to
that answers no result from DB.
luna://com.webos.service.capture/executeOneShot with method: DISPLAY
writes a PNG of the screen, web apps included, at the size asked for.
Home input titles (G3, webOS 9.2.2)¶
HDMI launch points added by Native Tv are bookmarks with systemApp: false.
LG's HomeAppListComponent/View/AppTile.qml hides a focused tile's title
unless titleVisible is set; otherwise it defaults to systemApp.
applicationManager/updateLaunchPoint accepts titleVisible: true, although
the on-TV schema does not list it. A read-back preserved the field and the
physical Home screen displayed the title immediately, without a Home restart
or QML modification. Updating the title can therefore show the port and EIM's
CEC names on LG's own Home screen. Long titles use LG's scrolling text.
Taking over Home (G3, webOS 9.2.2)¶
- The Home button opens
com.webos.app.homewhatevergeneral.defaultAppsnames: surface-manager launches it withmode: "hotKey". Back out of an app opens it through SAM'slast_input_handler,mode: "last_input". Unlike webOS 10.3 (above), a replacement Home has to bring itself back after LG's appears: LG's showed for 0.17 s after Back and 0.31 s after Home before Native Tv Home replaced it. defaultApps.homewas gone after each full restart, other entries kept.defaultApps.idleAppnaming another app does not change where Back out of the last app goes: stillcom.webos.app.homethroughlast_input_handler.- A compositor key filter ahead of LG's that accepts
Qt.Key_Super_L(the Home key) and launches an app replaces LG's Home entirely: surface-manager launches that app inhotKeymode, and LG's Home never shows. The filter is loaded from configd at boot, before any Native Tv process runs. - An app declaring
"appCategory": ["home"]installs through the developer install service and is accepted asdefaultApps.home. - The TV starts on the app
physicalLastInputAppandlastInputAppname, and a web app is accepted there. After a cold start the web app is opened throughcom.webos.app.inputcommon, and SAM lists the input app's process as the web app's.closeByAppIdthen answers true without closing it, and an install over it waits inappInstallService/statusstate"app closing"with the app locked (launchanswers "app is locked") until the TV restarts. Opened any other way, the same app closes and reinstalls normally. - From suspend, the TV comes back on whatever was in front.
- The Home button is evdev code 773 (
IR_KEY_HOME, 781, in/usr/share/X11/xkb/keycodes/lg, less xkb's 8), as on a B4 with webOS 10.3. A web app never sees it; held, it reaches/dev/inputas down and, later, up. - A web app gets OK (13) down and up, and Back (461).
- A web app reports
devicePixelRatio2 at 1920x1080. That value alone does not establish render resolution: the B3 compositor check below found a 1920x1080 viewport while JavaScript still reported 2. PalmServiceBridgein the app's own page,file://orhttp://localhost, can launchcom.webos.app.home, but called about 23 s after a cold start it opened nothing.luna-sendrun over SSH with stdin at end of file exits 0 and prints nothing; with stdin held open (sleep 5 | luna-send ...), or from node'sexecFile, it answers.
Cold start with Native Tv Home as the start-up app (webOS 9.2.2, G3)¶
Measured on 17 October 2026 by rebooting over SSH with lastInputApp naming com.tvweb.home, capturing the screen with com.webos.service.capture/executeOneShot (method DISPLAY) about once a second:
- SSH answers about 36 s after the reboot, and the Native Tv server about 45 s after it.
- From about 36 s the application manager names
com.tvweb.homeas the foreground app, but the screen shows the input or channel the TV was last on (Live TV, or HDMI 4), and the app's page never loads the view: no heartbeat arrives, while the same page opened later loads it within a second. applicationManager/launchofcom.tvweb.homefrom the server after that (about 52 s) draws it.- The TV's own
defaultApps.homeis unset after each of these reboots. - Home pressed (over SSAP) at about 37 s brought LG's Home to the front: drawn in one run, black for about 6 s in another. The compositor key filter that sends Home to
com.tvweb.homefrom the server's start onwards had not done so. /var/logholds CRIU dump and restore logs forcom.webos.app.homeandcom.webos.app.inputcommon, so those two are restored from snapshots at boot; whether that is why the started app is not drawn is not established.
Replacing LG's Home under its id (webOS 9.2.2, G3)¶
Measured on 17 October 2026 on an OLED55G36LA with a web app's directory
bind-mounted over /usr/palm/applications/com.webos.app.home, its
appinfo.json naming com.webos.app.home with type: "web".
- sam takes the type change. After a
profile.blockedAppListnudge,getAppInforeported the app aswebwithsystemApp: trueanddefaultWindowType: "card", read on the first poll. Unmounting and nudging again brought backnative. - Everything that opens Home opens it. The Home button (surface-manager,
mode: "hotKey") drew it 0.08 s after the press, Back out of the last app and closing the app in front (sam'slast_input_handler,mode: "last_input") 0.06 s after the launch, and waking from standby (bootManager) on Home. LG's Home never drew. LG's own Home is a card window too (NL_VSC_WEBOS_WINDOW_TYPE_CARD), and WebAppMgr has no home window type. The compositor launches it with{"activateType": "home", "launchType": "homeKey"}. - Nothing calls LG's Home as a service. No
luna://com.webos.app.homeappears under/usr/lib/qt5/qmlor/usr/palm/applications; the compositor's key filters name the id only to launch it. Toasts sent withsourceIdcom.webos.app.homestill showed. - The type must not change under a running instance. With the web page
still running, sam rereading LG's native manifest left
runninglisting anativeapp with the web page's process:closeByAppIdanswered "Message status unknown", the nextlaunchhung for 8 s, and the screen went black until Live TV was launched.closeByAppIdon the web app only sends it to the background; WebAppMgr'skillApp { appId }ends it, and sam then drops it. - The working order is: mount or unmount, nudge, then stop the old
instance (kill LG's process, or
killAppthe page). Where that instance was in front,last_input_handlerlaunched Home again 1.0 to 1.2 s later, as the new app. Each direction took 2.1 to 2.2 s, nearly all of it the nudge's wait. Killed in the background, LG's Home was not started again. - LG's Home started fresh took about 3 s to draw: its window was visible
1.2 s after the switch and it logged
NL_HOME_SHOWN1.9 s after that. Restored from its snapshot it drew in 0.2 to 0.3 s. - Cold start. LG's Home starts 5 s into boot (
BootTimeAppsin/etc/palm/sam-conf-tv.json), in the background while the TV shows its last input (12.6 s). A webosbrewinit.dhook ran at 24.8 s; mounted, nudged and with LG's process killed it was done at 28.5 s, and Home pressed afterwards opened the web app. The mount does not survive a reboot. - Standby. The mount and sam's reading of it outlast suspend: switched on
with the remote,
bootManagerlaunched the web app as Home. - An empty layout hides LG's Home before the hook. With
home_layoutShelfView.xmlandhome_layout.xmlin/mnt/lg/cmn_data/manifestholding a<layout type="ShelfView" bgColor="#000000">with an empty<firstPage>, LG's Home started fresh loggedNL_HOME_SHOWNand drew a completely black screen, keys included. At boot it started fresh and read it: with the hooks held back 25 s by a test hook, Home pressed at 32.8 s showed LG's Home, black (every captured pixel 0), until the mount at about 53 s. Its wallpaper comes only from its own bundled images (backgroundImageIdopt1 to opt3), so the layout cannot show anything else. - The key filter can answer Home before any hook. Native Tv's filter,
loaded by surface-manager from configd, called
lunaCall.send("com.webos.applicationManager", "/getAppInfo", ...)andlunaCall.send("com.webos.notification", "/createToast", ...)withsourceIdlunaCall.appId, as LG'sappLaunch.jsdoes. With the hooks held back, Home pressed at 27.9 s with nothing mounted showed the toast 0.04 s later, over HDMI 4, and LG's Home was not launched; pressed at 54.2 s, after the mount, it opened the web app in 0.19 s. - Back out of an app before the hook also reaches LG's Home, through
last_input_handler, not the key filter. Closing the browser at 45.9 s, with the hooks held back, showed the empty layout's black screen (every captured pixel 0); Home pressed over it at 51 s showed the toast. - A left web app keeps running.
com.tvweb.home, an earlier build's Home app withcloseOnBackgroundfalse, stayed inapplicationManager/runningafter another app came to the front, for minutes, so a removal waiting for it to stop never came.com.palm.webappmanager/killAppwith its id closed it; sam stopped listing it, and its removal went through.
Checked on 18 October 2026 on the same TV, with Native Tv Home in the place:
- LG's other screens still work over it. The Input picker
(
com.webos.app.inputcommon) opened over it and switched to HDMI 4. A toast and acreateAlertalert showed, and the alert closed with OK. The notification list (com.webos.app.notificationcenter), Search (com.webos.app.voice), the LG Account panel (com.webos.app.overlaymembership) and the full account app (com.webos.app.membership) opened over it, loaded their content, and closing them brought it back. Search loggedNL_ACTIVATE_SEARCHwithforeground_appcom.webos.app.home, as it does over LG's Home, and a result opened HBO Max at the title. Quick settings (the Settings key) opened over it. - LG's apps that name the id launch it. First-use setup and the on-timer
in Settings launch
com.webos.app.home, so open Native Tv Home. Settings and the weather location app keep the weather location underappIdcom.webos.app.home, keylocation, in the settings service, not in the app. - The notification list has no other way in. LG's Home has a sidebar with
the account, notifications, settings and search; neither the notification
list nor Search has a launch point (
visible: false).getAppInfogives each one'stitle,iconandfolderPath. Search'sicon.pngis a pair of circular arrows. - Without the empty layout, a cold start still showed no LG Home. With
homeAutoLaunchon and HDMI 4 last, the screen stayed on HDMI 4 from 26 s; the mount was in place at 30 s, andcom.webos.service.preloadmanagerlaunchedcom.webos.app.homeat 53 s, after it. - The empty layout outlives Native Tv. With it in place, the server killed
without releasing and
/var/lib/tvwebmoved aside, Home after a reboot drew black.rm -rf /mnt/lg/cmn_data/manifest /tmp/checkpoint/*com.webos.app.home* /mnt/lg/cmn_data/checkpoint/*com.webos.app.home* && rebootbrought LG's Home back on its default layout.
LG Home's recent apps (G3, webOS 9.2.2)¶
Read on 19 October 2026 from LG's Home's QML under the Native Tv Home mount, and tried over SSH.
- The panel is part of LG's Home. Back on LG's Home's first page sets
uiController.isRecentMode(UIController.qmlshowRecents), which slidesRecents.qmlup from the bottom. NoactivateTypeor other launch parameter opens it, so nothing outside LG's Home can show it. - Its list is
com.webos.service.recent, served by the surface manager:listRecentsanswersrecentsAppList, newest first, each withappId,title,cardSnapShotFilePath(a JPEG in/tmp/snapshots/<id>/) andcustomImageFilePath(Netflix namesRECENTS.pngof its own). It is not the running list: Apple TV was listed after it had stopped, and YouTube and the browser, kept running in the background, were not. - Removing closes. LG's Close and Close all call only
removeRecent { appId }andremoveAllRecents {}. Each closed the apps it removed: Netflix leftapplicationManager/runningwithin 2 s, and Close all took Netflix and the Native Tv app with it while YouTube and the browser, unlisted, kept running. - A launched app joins the list once it has been left; launching Home over it is enough.
- On a G5 (webOS 10.3.1) the service is there with the same answers, but
removing does not close: Netflix was still in
runningafterremoveRecentand afterremoveAllRecents, andcloseByAppIdthen closed it. Snapshots are in/tmp, so apps left before the TV restarted are listed withcardSnapShotFilePathempty and only theirsplashBackground. Checked on 19 October 2026.
Channels and the guide (G3, webOS 9.2.2)¶
com.webos.service.apiadapter/tv/getChannelList(the method behind SSAP'stv/getChannelList) lists the tuner's channels withchannelId,channelNumber,channelName,Radio,skippedandInvisible: 182 terrestrial channels in London.com.webos.service.iepg/getChannelListanswered with none.com.webos.service.apiadapter/tv/openChannel { channelId }tunes and brings Live TV to the front, from any app. Launchingcom.webos.app.livetvwithchannelIdorchannelNumberdoes not change the channel while Live TV is open.com.webos.service.apiadapter/tv/getChannelCurrentProgramInfo { channelId }gives the programme on now for any channel, withstartTimeandendTimein UTC as"2026,10,17,13,40,00"andlocalStartTime/localEndTimein the TV's zone, once a channel has been tuned since the TV started; before that it has no programme.tv/getChannelProgramInfoandiepg/getEventListreturned empty programme lists throughout.com.webos.service.utp.boot/getLastChannelIdnames the channel Live TV is on, including one reached with the remote's Channel Up within Live TV, which changes nothing in sam's foreground. Measured on 18 October 2026.
Native Tv Home's view and the foreground (G3, webOS 9.2.2)¶
Measured on 18 October 2026 by launching apps over SSH and logging
applicationManager/getForegroundAppInfo's subscription.
- Launching
com.webos.app.homefrom Live TV, the view's/api/home/cataloguerequest reached the server about 0.2 s before sam's subscription namedcom.webos.app.home. Whatever the server learns from the foreground changing is not yet known when the view asks for its rows. - An app launched cold (Channel 4, BBC Sounds) is named once, 2 to 3 s after the
launch, with nothing in between. Once, during the first launch of BBC Sounds
that session, LG's app store (
com.webos.app.discovery) was named for about 10 s before it; this could not be made to happen again.
Which window has the remote (webOS 6.4.0, C1)¶
com.webos.applicationManager/getForegroundAppInfonames only the app beneath LG's own windows: with Settings, User Guide, Home or Quick Settings open over HDMI 3 it still reportscom.webos.app.hdmi3.com.webos.surfacemanager/getForegroundAppInfolists the windows on screen, each withappId,displayIdandwindowType: HDMI 3 as_WEBOS_WINDOW_TYPE_CARD, Settings (com.palm.app.settings) as_WEBOS_WINDOW_TYPE_OVERLAY, and Home (com.webos.app.home) as_WEBOS_WINDOW_TYPE_HOME, not as an overlay. Opening User Guide from Settings replaces the overlay withcom.webos.app.tvuserguide.- Quick Settings (
com.webos.app.quicksettings) is not in that list. It is incom.webos.surfacemanager/getFocusedWindowInfoandgetForegroundWindowInfo, asSYSTEM_UI_TYPE_OVERLAY. The focused window is the one the remote's keys reach. - All three accept
subscribe: true. SurfaceManager's replies are formatted JSON over several lines even without luna-send's-f.
Disconnected input devices (webOS 6.4.0, C1)¶
A stale evdev descriptor can remain readable to select while reads fail or
return EOF. Retrying without closing it creates a busy loop. On 14 October
2026, the remote-button worker reached 8.16 million read calls with only
451 KB read, and a top sample showed 85% CPU. Reopening its devices stopped
the loop. The patched worker closes EOF/permanent-error descriptors, retains
EAGAIN/EINTR descriptors, and retries discovery every five seconds. Four
minutes after deployment it had 189 read calls and 0.1% lifetime CPU.
Home screen (webOS 9.2.2, C2)¶
The home app is com.webos.app.home, a native QML app in
/usr/palm/applications/com.webos.app.home/qml. The source is readable. It
uses the "multiple home" layout (isMultipleHome), built from
Standalone/Components.
The first screen is laid out from an XML file. MainView_M.qml loads
/mnt/lg/cmn_data/manifest/home_layoutShelfView.xml (or home_layout.xml,
depending on testLayout), and falls back to the copy in
qml/UserInterfaceLayer/ when that is missing or empty. The folder does not
exist on a stock C2 and is writable. LG's file lists four parts:
type |
On screen |
|---|---|
Hero |
The banner, and the profile, notification, settings and search icons beside it |
Qcard |
The coloured "Quick Card" ribbon: Get Special Offers, Sports, Gaming, Music |
AppList |
The app tiles |
AdShelf |
Recent Input and Device Functions (Edit App List, TV Guide, User Guide, Home Hub) |
A layout with only <item type="AppList" itemX="24" itemY="24" itemWidth="1872"
itemHeight="173" focus="true" option="webOS24"/> shows the app tiles alone at
the top. The <layout> element also takes bgColor, and type can be
ShelfView, LifeStyle or TabView.
Moving the parts is not possible. The parts stack one under another from
the top: itemY on the app list, vMargin on <layout>, and a margin item
(whose MarginComponent.qml is missing from this firmware) all left the app
tiles at the top. Only the banner uses its itemY.
The rows below the first screen (Live TV, LG Channels, Shopping, Amazon,
Editor's Pick and others) come from LG's server, as ai_home_info in the reply
to a service_setting_secure getConfig request with requester: ai_home.
The home app logs that reply to /var/log/home. No setting or layout attribute
turns them off: Model/ShelfList.js _filterShelfItem() decides which are
shown, so removing them means changing that file.
With Home Promotion off (general.homePromotion), the banner does not go
away: it shows "Start a new experience with webOS." and a Go to Apps button.
With Content Recommendation off as well (other.contentRecommendation), the
advert row shows Recent Input and Device Functions instead.
An HDMI input can be a Home tile. applicationManager/addLaunchPoint with
{ id: "com.webos.app.hdmi2", title: "Mac", params: {} } is accepted, and the
tile shows LG's HDMI icon and opens the input.
A tile can be moved. applicationManager/moveLaunchPoint with
{ launchPointId, position } (0 is first) changes the order the app manager
lists, and the order stays, but the home app shows it only once it starts
again. A tile added with addLaunchPoint goes at the end of the apps, and
shows straight away.
The banner cannot be blanked. The layout's other banner types,
AlwaysReadyPreview and Seiro, in the Hero item's place, draw the same
picture, "Start a new experience with webOS." and Go to Apps button while Home
Promotion is off. That picture and text are in the home app's own files.
The home app reads its layout only when it starts. Reopening Home does not reload it. Restarting it:
applicationManager/closeByAppIdonly sends it to the background.- Killing the process makes the TV restore it from its CRIU checkpoint, so the
old layout comes back. The checkpoint is in
/tmp/checkpoint/com.webos.app.home, restored from a copy in/mnt/lg/cmn_data/checkpoint/com.webos.app.home(LG'scriu_copy_img.shcopies one to the other at boot). With only the/tmpcopy deleted, the kill restored the flash copy and the old layout; with both deleted, it starts fresh. - A fresh start makes a new checkpoint straight away, and a restart afterwards restores that one.
At boot the home app starts fresh. After reboot (/sys/power/mode reads
resume), it was a new process (pid 2442 is simply its place in the boot
order), and the copy in flash was rejected: criu images( com.webos.app.home )
hashes are different !!.. will be deleted in dmesg. So:
- The layout file survives a restart, and a power-on after the TV was unplugged
at the wall, with nothing re-applied, since a fresh start reads it. Both
booted with
/sys/power/modereadingresumeand the home app started fresh. - A bind mount over one of the app's files (a changed
ShelfList.js) does not: the home app starts about 5 s into boot, before anything a rooted TV runs, so it has to be mounted again and the home app restarted.
Undoing it: deleting /mnt/lg/cmn_data/manifest and restarting the home app
brings back LG's layout. Launch points added with addLaunchPoint are removed
with removeLaunchPoint.
Which TVs have this home app. Native Tv's Home screen layout is offered
only on webOS 9. webOS 3 and 4 have a different, plainer home app, and webOS 10
and later have a Flutter one (its log lines come from flutter-client). The
QML has code for LG's webOS 23 (webOS23Test, the webOS23 app list style),
so a webOS 8 TV may read the same layout file; that has not been tried.
The clock since boot stops in suspend (webOS 4.4.3, B8)¶
With Quick Start, the B8 suspends in standby, and /proc/uptime and /proc/stat's btime leave the suspended time out: rebooted at 07:47 UTC and put in standby twice, it gave its boot as 18:18 the same day. Time since boot, and a boot time worked out from it, are wrong on such a TV after its first standby.
Keeping a TV awake while off (webOS 4.4.3, B8)¶
The question was whether the B8 could stay reachable while switched off, as
the C2 does with LG's Stay connected (general.alwaysOn, Active Standby at
12.5 W). It cannot in any useful way.
- Switching off passes through Active Standby: screen off, everything running, at about 37 W on an OLED65B8SLC (50 W on). With Quick Start+ it then suspends to RAM, and the PSU clicks off. Panel maintenance after switch-off runs in that Active Standby state.
com.webos.service.tvpowertakes votes. Programs register withpower/registerSuspendRequest,registerPrepareSuspendandregisterActiveStandbyRequest({ clientName, subscribe: true }), and answer with the matchingresponse…method.power/getClientListlists them; besides LG's services,homekit,physical-device-managerandwebos-connman-adapterask for Active Standby, and the AirPlay module votes on suspend. homekit answers{ "clientName", "ack": true|false, "timestamp" }, echoing the request's timestamp.- Refusing to suspend does not keep it awake. With a client registered on
all three answering
ack: falseto suspend andack: trueto Active Standby, the next switch-off went from 37 W to 0 W and the TV booted from scratch when switched on again (uptime 156 s, power-on reasonremoteKey), instead of resuming. A switch-off with no such client resumed with its uptime intact. - Even held there, 37 W around the clock is about 0.9 kWh a day. The low-power awake state behind Stay connected arrived with LG's 2022 TVs (webOS 7).
Standby power with Stay connected (webOS 9.2.2, C2)¶
With general.alwaysOn on and the TV switched off (power/getPowerState
reads Active Standby), an OLED42C24LA drew 11.9 to 12.2 W at the wall. The
processor is fixed at 1.4 GHz (the only frequency offered, performance
governor), and LG runs three of its four cores, switching cores on and off
itself (224 core starts in five hours). About 40% of those three cores was in
use: ls-hubd, iconnectivity, Native Tv's server and YouTube kept ready.
None of it showed at the wall:
| Change | Draw |
|---|---|
| None | 12.0 W |
| Native Tv's server and watchdog stopped | 11.9 to 12.2 W |
| Also down to two cores (LG kept bringing a third back) | 11.9 to 12.1 W |
iconnectivity cannot be stopped: ls-hubd starts it again on demand within
5 s. The load average of about 12 comes from a dozen of LG's driver threads in
uninterruptible sleep, not from work.
LG's blocked-app list on webOS 10 (C2, webOS 10.3.1)¶
On a C2 updated to webOS 10.3.1, adding an app on the Home screen
(com.webos.app.camera) to configd's profile.blockedAppList left it on Home
and sam's pid unchanged, checked from 0.01 s to 10 s after. On webOS 9.2.2 the
same change takes the app off Home within 2 s, which is how tile hiding and
screen savers make sam reread apps without restarting it (#366). /usr/sbin/sam
names profile.blockedAppList on both, so webOS 10's sam has the setting and
does not act on it.
What webOS 10's sam does act on is applicationManager/blockSystemApp followed
by releaseBlockSystemApp for one app id. On a C5 (webOS 10.3.1) with a bind
mount over com.webos.app.screensaver that changed its manifest from Flutter
to QML, the two calls returned within the same second, getAppInfo reported
type: qml at once, sam kept its pid, and LG's
/var/preferences/com.webos.applicationManager/blockedSystemAppList/USA.json
(eight ids there) was byte-identical before and after. The block does not stop
a running instance. The screen saver then ran under qml-runner, and two screen
saver, standby and wake cycles left the picture intact (YouTube reached the
MAIN sink with activation: true). The same calls have run at every boot of an
LG Home replacement on that C5 since 2026-10-11. A reboot between the two calls
would leave the app blocked, so they stay together and the release is retried.
webOS 11 changes the block's parameters. On a G3 (OLED65G36LA, webOS 11.2.0,
firmware 43.21.71) /etc/palm/schemas/sam/applicationManager.blockSystemApp.schema
requires forceBlockSystemApp as well as id ("force blocking system app for
WEE platfrom"), and {"id":...} alone is answered errorCode 2, "invalid
parameters"; a C2 on webOS 10.3.1 requires only id. With
"forceBlockSystemApp": false the block returned true, the release (still id
alone) took it out, blockedSystemAppList/GRC.json was byte-identical
afterwards and sam kept its pid. A QML screen saver over the Flutter one was then
reported as type: qml, ran, and held through standby and a full reboot, with
ARC sound and HDMI-CEC working afterwards (#768). The same G3 has no
profile.blockedAppList: getConfigs lists it in missingConfigs.
On that C5 a standby after about a day of uptime ends in LG's own refresh
reboot (PowerOnReason: rebootByOnRegular, next to "Instant Boot Refresh
Timeout" in tvpowerd), which clears tmpfs and bind mounts; and sam came back
as the same pid after it, so a pid check alone does not show a restart there:
ps -o etime and /proc/uptime do.
The TV's time zone (C5, webOS 10.3.1)¶
com.webos.service.systemservice/time/getSystemTime gives the time zone with
the time: localtime as year, month, day, hour, minute and second, utc in
Unix seconds, offset in minutes (120 in Ljubljana in October), timezone
(Europe/Ljubljana), TZ (CEST), isDST and timeValid. localtime less
utc matched offset. Watch time works its offset out from localtime and
utc. Which of these fields older webOS versions give is not yet known.
Toasts as the screen comes on (C4, webOS 10.3.1)¶
A toast sent through com.webos.notification/createToast in the moment
turnOnScreen brings the screen back is accepted (returnValue: true) but not
seen. The same toast sent with the screen already on is. Screen-time limits
wait 5 seconds after the screen comes on before sending one.
turnOffScreen while LG's screen saver is showing does not hold: tvpower goes
from Screen Saver to Screen Off and back to Active 0.2 s later, with the screen
on. From Active it holds. Screen-time limits dismiss the screen saver with
Back first, as the screen saver tab does.
Switching off (C5, webOS 10.3.1)¶
power/powerOff with reason remoteKey switched the TV off, going Active,
Active Standby 3.3 s after the request, then Power Off 5.7 s later, but its
answer was taken as a failure: a second powerOff with reason localKey got
"com.webos.service.tvpower/power is busy". From Power Off, switching on with
the remote booted the TV from scratch (uptime 42 s), so the server started
again.
The Magic Remote's battery (C4, webOS 10.3.1)¶
/mnt/lg/cmn_data/mrcu/mrcu1.info is written when the remote pairs and not
after: on a C4 its time and Paired Time were the same, a day old. Its
Battery = 52(M) 35(L) is not the charge. /usr/sbin/lginput2, which writes
it, logs the same pair as Battery threshold : Mid %d, Low %d, and an MR24 on
a C4, the remote on a C5 and the remotes in the test fixtures all read 52.
mrcu1.scd has BA 35, the Low threshold.
Swapping the batteries left mrcu1.info unchanged. The remote's reconnect
went out from com.webos.service.mrcu as getConnectionStatus replies, with
no battery in them, and the binary .dcd file beside it was rewritten. Nothing
else showed a level: /sys/class/power_supply is empty, the system log has
only button presses, and getDiagnosisItem stays empty. getDeviceInfo
answers "Invalid Parameter" to {}, deviceId 0 and 1, and deviceType
mrcu, MRCU and 0.
The remote has the standard Battery Service, and com.webos.service.bluetooth2
reads it. The remote is in device/getStatus (name LGE MR24, type ble), but
gatt/getServices answers "Device is not connected to profile" until
gatt/connect is called with its address, which returns a clientId. After
gatt/discoverServices, the remote lists 180f among its services, and
gatt/readCharacteristicValue with that clientId, service
0000180f-0000-1000-8000-00805f9b34fb and characteristic
00002a19-0000-1000-8000-00805f9b34fb returned "bytes": [61] with old
batteries in it. The call takes no address. The characteristic also has
notify. gatt/disconnect with the clientId ended it, and the remote worked
after each of the two connections. How often this can be done
without disturbing lginput2's own connection, and whether webOS 9 and earlier
have these calls, is not yet known.
On a B8 (4.4.3) and a C2 (9.2.2), getConnectionStatus asked once answers
isBleRemocon: false even with the Magic Remote connected. Subscribed, the
update sent as the remote wakes has connected: true, isBleRemocon: true, and
the one as it sleeps keeps isBleRemocon: true.
On the B8, getDeviceInfo with deviceName MagicRemote_1 answers
batteryLevel 49, and 63 once other batteries were put in: the charge, not a
threshold. Its mrcu1.info (in /mnt/lg/cmn_data/btsvc) has no battery line.
Its gatt/connect answers appId and no clientId. The C2 answers
batteryLevel "-".
A user's webOS 5 TV, on v0.97.0, the first release whose read reached
gatt/connect, had a remote with no pointer and some buttons ignored after the
TV woke from standby, until a reboot. Not yet confirmed from its log; the read
over Bluetooth is held to webOS 9 and 10 meanwhile.
On the B8, lginput2 once started a diagnostic capture, a
/tmp/var/log/<date>_MRCU.log with columns for motion, RSSI, voltage,
temperature and gyro, beside a ManualDevice-<remote MAC>-rawInput.dsf. A new
mrcu_LS2 thread started with it and used a whole core until the TV was
rebooted, through a night in standby. lginput2's luna methods include
enableLoggingMotion, getSensorData and enablePrintRfStatus, none of which
Native Tv calls; getConnectionStatus and getDeviceInfo left it at 0%.
No firewall in the kernel (50QNED80A6A, webOS 10)¶
A 50QNED80A6A on firmware 33.31.61 (LG's webOS 25, kernel 5.4.268, rooted
with Dangbro) has iptables 1.8.7 (legacy) but no packet filtering in its
kernel: iptables fails with can't initialize iptables table 'filter' after
modprobe finds no ip_tables module, /proc/net/ip_tables_names and
/proc/net/netfilter do not exist, and there is no nft. Developer Mode's
debugger on port 9998 stays reachable from the network (#699).
/etc/systemd/system/scripts/webapp-mgr.sh exports ENABLE_INSPECTOR=1 and
starts WebAppMgr with --remote-debugging-port=9998 whatever the mode (its
comment says "if in developer mode", but nothing tests for it). With Developer
Mode on (/var/luna/preferences/devmode_enabled is a directory), both a C2
(webOS 9.2.2) and the second TV in #699 listen on 0.0.0.0:9998. An earlier
note here that a C2 did not listen on 9998 was mistaken. LG's browser engine,
/usr/lib/libcbe.so, names remote-debugging-port but no
remote-debugging-address, so the debugger cannot be bound to loopback by a
switch: without a firewall, only leaving out the port switch, which needs
WebAppMgr restarted, or turning Developer Mode off closes it.
The compositor's key filters (webOS 4.4.3, B8; webOS 9.2.2, C2)¶
The compositor (surface-manager) runs every remote key through a chain of
JavaScript filters named in the configd key
com.webos.surfacemanager.keyFilters: { file, handler } pairs, LG's from
/usr/lib/qt5/qml/KeyFilters/ (appLaunch.js, systemUi.js and others; 12
entries on a B8, 18 on a C2). Each handler returns KeyPolicy.NextPolicy to
hand the key on, Accepted to consume it, or NotAccepted to pass it to the
app in front. Remote Keys puts its own filter first.
- Rebuilt on a change. Writing a new value to the key makes the compositor load its filters again at once. configd does not report a value written unchanged, so a filter file changed in place needs the entry taken out and put back.
- Read at boot. configd keeps the value, and the compositor loads the chain before Native Tv starts: after a reboot, a key mapped there opened its app 35 s (C2) and 40 s (B8) in, with the server not yet running.
- A missing file is skipped. With the first entry naming a deleted file, after a reboot the next filters still ran: the TV key opened Live TV through LG's filter on both TVs.
- Keys sent over the network go through it.
com.webos.service.networkinput/test/sendKeyCodewith a Linux key code (theIR_KEY_*value in/usr/share/X11/xkb/keycodes/lgless 8: Blue 401, TV 377) reached a mapped key's filter like the remote's own press. - A filter can send keys over the network. On a C3 (webOS 10.2.2) the
filter's own
lunaCall.sendtonetworkinput/test/sendKeyCodewith play 207, pause 119, stop 128, rewind 168, fast forward 208, volume up 115, volume down 114 and mute 113 acted as the remote's keys. A play/pause toggle that first askedcom.webos.service.acb/getForegroundAppInfo(thencom.webos.media's) and sent pause or play did nothing. - A rebuild re-runs LG's
init()s. In Game mode each write of the key opened the Game Dashboard (NL_GAMEDASHBOARD_ENTERED,"entered_by":"HotKey"in/var/log/messages) on the C2. Launching an app the same way does not. - Filters can subscribe over luna. LG's use the global
lunaCall.subscribe( service, method, payload, callback, true). A filter subscribed tocom.webos.service.config/getConfigsgets a changed value about 0.1 s aftersetConfigs, on the B8 and the C2, so its behaviour can change with no rebuild. - The voice assistants' buttons are ordinary hotkeys. On a C2 (webOS 9.2.2)
appLaunch.jshandlesKey_webOS_ALEXA(IR 1094) andKey_webOS_GoogleVoice(IR 1125) like the streaming buttons, launching the assistant's app on a press, while the microphone button (Key_webOS_Voice, RF 436) goes to voice control. The same file names about 20 regional streaming buttons (Hotstar, Stan, Wavve, U-Next, TVer and others). - The voice assistants' buttons are ordinary hotkeys. On a C2 (webOS 9.2.2)
appLaunch.jshandlesKey_webOS_ALEXA(IR 1094) andKey_webOS_GoogleVoice(IR 1125) like the streaming buttons, launching the assistant's app on a press, while the microphone button (Key_webOS_Voice, RF 436) goes to voice control. The same file names about 20 regional streaming buttons (Hotstar, Stan, Wavve, U-Next, TVer and others). - Filters get the compositor's timers.
StarfishKeyFilter.qmlhands every filtergenericTimer(set(ms, callback),cancel,isRunning), as LG'sappLaunch.jsuses it. On a change to the key it cancels everygenericTimer, destroys the filters and loads them again, running eachinit(). On a G3 (webOS 9.2.2), a 90 s timer set in Native Tv'sinit()ended its hold on Home: withstartingset and nothing mounted, Home 5 s and 30 s after a reload showed the toast and stayed where it was, and 96 s after it opened LG's Home.Date.now()cannot time this: the system log starts at 2023-01-01 and jumps when the TV sets its clock. - Home sent over the network does nothing. On the G3,
sendKeyCodewith 773 (IR_KEY_HOME781 less 8) neither opened Home nor reached the hold, while Search (217) and Settings (139) did. Writing 773 to the remote's own input device (LGE RCUin/proc/bus/input/devices,event0) acted like the remote's Home. - configd takes any name and cannot forget one.
setConfigsstores a key it has never heard of (nativetv.remoteKeys) in/mnt/lg/cmn_data/var/preferences/configd_factory_db.json, kept across reboots. There is no delete method, and settingnullis ignored.
Native key filters (C5, webOS 11.2.0)¶
- No JavaScript filters.
surface-managerruns on Weston (/usr/share/weston/weston.iniloadsstarfish-keyfilters.so), and the filter chain iscom.webos.surfacemanager.keyFiltersCpp:{ file, handler }pairs naming/usr/lib/libpreProcess.so,libsystemUI.soandlibappLaunch.so./usr/lib/qt5/qml/KeyFilters/does not exist, thoughcom.webos.surfacemanager.keyFiltersstill names its files. - Streaming buttons come from
other.mapping_info.handleCPHotkeysreads the settings service'sother.mapping_info(37 entries, Netflix to YouTube, each{ app_id, launch_param, isActive }) at each press; LG's server sends it, andlibappLaunch.soalso keeps a copy in the microcontroller's database. Withnetflix.app_idchanged, the next Netflix press (IR 1045, written to the remote's input device as 1037) launched the new app, callercom.webos.starfish.keyfilters, modehotKey; a real press on an MR25GA did the same. WithisActive: falseit launched nothing and showed a toast. - Some keys come from
com.webos.keyaction.*.libappLaunch.soreadstvGuide,inputHub,voice,muteX3,sleep,aspectRatio,pictureModeandlocalEnter, at each press. Guide (IR 370) set to{ action: "launch", id }launched that app from Home; on HDMI 2 the input app took the key and opened its own guide, with or withoutfgAppIdsForByPass. Input Hub (IR 1031) followed its value on HDMI 2 too. Input (IR 249) openedcom.webos.app.quickinputpickerand Red (IR 406) did nothing new, whateverinputHubandcolorRedheld. - Keys sent over the network still reach them.
sendKeyCodewith 362 (Guide) openedcom.webos.app.livemenu, launched bycom.webos.starfish.keyfilters. Codes above the remote's own input devices' range (Alexa 1086, the ? button 1124, 123 994) reached nothing, written to any of them. lginput2logs every press by name.NL_BUTTON_CLICKin/var/log/messagesgivesremote_typeandbutton_type. On an MR25GA:KEY_HOMEDASHBOARD(the house in a circle; openscom.webos.app.homeconnect-overlaythroughkeyaction.inputHub),KEY_MULTIKEY(?),KEY_GUIDE,KEY_VOICE(AI),KEY_HOME,KEY_SCREEN_REMOTE(123),KEY_ALEXAVOICE,KEY_NETFLIX,KEY_AMAZON.- The ? button is LG's custom button. A press launches
other.customShortPress({ id, type: "app", params }, LG's default the input picker) with modecustomkey, a holdother.customLongPress(Accessibility). A change applies at the next press. Withtype: "None"a press openedcom.webos.app.accessibility. - AI, Home, 123 and Alexa read no value. AI goes to
com.webos.service.voiceconductorwhateverkeyaction.voiceholds; Home launchescom.webos.app.homefrom the filter; 123 stays in the compositor (NL_SCREEN_REMOTE_APP_USE); Alexa is launched byamazon.alexa.adapter.plugin. - The AI button goes to the voice assistant alone.
voiceconductorreads no value for it: itsvoiceframeworksettings name none, andkeyaction.voicedid not change it. Raw events are not readable: a reader on every/dev/input/event*that opened saw none of the MR25GA's presses, aslginput2holds them.mrcu/getButtonHistorylists presses but sends no updates to a subscriber, andvoiceconductor/getVoiceUiEventsanswerssubscribed: false. Withvoiceconductor.servicestopped, presses were still logged asNL_BUTTON_CLICKand nothing started the service again; an app launched from that log line was in front 0.6 to 1 s after the press, with nothing of LG's on screen, before and after a switch off and on. - The Alexa button goes to Amazon's adapter.
libappLaunch.sonamesamazon.alexa.adapter.pluginandcb_launchAlexaHotkey; the adapter, a dynamic service (Type=dynamic, run throughjailer), showed "Amazon Alexa est en cours de chargement" 1 to 1.5 s after the press and launchedamazon.alexa.view2.5 s after it, then the terms, withvoiceconductorstopped as well as running. With the view blocked byblockSystemApp { id, forceBlockSystemApp: false }, sam logged the launch and nothing opened;getAppInfoon a blocked app returnsreturnValue: false, a second blockerrorCode1 "already blocked:", and a release of an app not blocked returnValue: true. The adapter launched the view up to 13 s after a press. - Toasts can be refused, not closed.
notification/closeToastwith a toast's id returned true and the toast stayed its 5 s. Afternotification/disable(exceptionsoptional),createToastwas answered "Toast is blocked by []" and nothing was shown, then or after enable. A subscriber togetToastNotificationgets each toast with itssourceId. mapping_infois written back at each switch off and on. At Active Standby, 60 ms afterNL_POWER_STATE, and twice more on power-on, the settings service's subscribers got LG's entries again, from the copy kept for the microcontroller (com.webos.service.lowlevelstorage, dbidmicom). configd's key actions and the custom button kept their values. Not every write is announced: around another switch off and on the list was written back nine times, five of them with no message to the subscriber, the last 60 s after power-on.
Promoted stub apps (G3, webOS 9.2.2)¶
On 18 October 2026, with a network-wide ad blocker in the house switched off,
two apps appeared within 3 s of each other: webos.day (LG Streaming Week)
and com.miniclip.eightballpool (8 Ball Pool). Both have type: "stub",
internalInstallationOnly: true, requiredEULA: "generalTerms" and vendor
lgmtv.app@lgepartner.com, are removable, and are in
/media/cryptofs/apps/usr/palm/applications. Their image files were dated
14 September and 6 October, their appinfo.json the minute they arrived. The
notification list showed "Some apps are available for update" the same
minute. Neither name is on Native Tv's ad-blocking list.
Home screen (webOS 10 and 11)¶
From layout dumps in #612 (a C2 on 10.3.1, a B4 on 10.3.2, a C4 on 11.2.0) and others' work on webOS 10 (github.com/mareklarek/webos10-homescreen-customization and its issue 2).
- The home app is Flutter. Its layout is
/usr/palm/applications/com.webos.app.home/data/flutter_assets/assets/home.xml, a vertical list of items byid:margin(spacing, with a height),containerholdinggloballine(the side buttons) andherobanner,qcardList,appListandrecommendedShelf. The files were identical on the two webOS 10 TVs, US and EU. - webOS 11 differs:
home.xmlhas two pages, the first amypageitem (with a newhome_widget_template.xml), dropsgloballine, and the folder hasimg_background.webp. - No writable layout path. On the 11.2.0 C4,
lib/libapp.sonameshome.xml,home_layoutShelfView.xmlandhome_wee.xml, and the only/mnt/lg/path in it is the Gallery's AI Art folder. So unlike webOS 9 the layout can only be changed by mounting over the folder. - What works, from others on webOS 10: taking out
qcardListandrecommendedShelf; replacing the banner image (images/{hd,2k,4k}/bg_banner_img.png) and its text (ini18n, a symlink to/mnt/lg/wee/ui_l10n/...); shrinkinggloballineto 0 by 0, placed afterherobanner. Takinggloballineout left the screen black. Icon size is inlibapp.soand the clock item works only in the senior layout. - The home app runs as
flutter-client. On a C2 (webOS 10.3.1) its command line is/usr/bin/flutter-client -i com.webos.app.home, sopidof com.webos.app.homefinds nothing. Other Flutter apps run asflutter-clienttoo; the-iargument names the app. Killed with SIGTERM, the TV started it again with the changed layout. - Rows are stacked from their heights. With
qcardListandrecommendedShelfonly taken out, the apps row sat in the middle of the screen on a C2 (webOS 10). mareklarek's layout keeps it at the bottom by growingcontainerandherobannerto 1803 (from 900), so the removed height has to go to the banner. - An overlay mount is enough. The kernel has overlayfs: LG's folder as
lowerdirand a small folder with the changed files asupperdirapplied in 0.08 s on a G5 (10.3.1), against 0.54 s for copying the whole folder (28.7 MB, 525 files) and bind-mounting the copy. Restarting the home app (killing it) reads the new layout; no black picture was reported from it. Mounted from a webosbrewinit.dhook, the home app was running with the changed layout about 29 s after power-on.
What the player is doing (webOS 4.4.3, B8; webOS 9.2.2, C2)¶
- The B8 answers
com.webos.service.acb/getForegroundAppInfowith anacbspipeline list, each withplayStateNowandplayerType(external inputfor HDMI). The C2 has no such service ("Service does not exist"). - On the C2,
com.webos.media/getForegroundAppInfogivesforegroundAppInfo: [{ appId, playState, type: "media", mediaId, windowId }]: YouTube readplaying, thenpausedafter the remote's Pause key, and the list was empty on HDMI 2.com.webos.media/pausewith thatmediaIdansweredreturnValue: falseand did not pause.
Boot and app state (webOS 9.2.2, C2)¶
- The kernel command line has
snapshot resume=/dev/mmcblk0p51 criu_enabled. Apps such as the home app andcom.webos.app.inputcommonare checkpointed with CRIU and restored from it when killed; at boot the home app's copy in flash was rejected and it started fresh. /usr/sbin/snapshot-boot-manager --removediscards the memory image; the next boot is a slower "making" boot (/sys/power/modereadsmaking) that remakes it, and clears the CRIU copies in flash.com.webos.service.capture/executeOneShotwith{ path, method: "DISPLAY", width: 1920, height: 1080, format: "JPEG" }saves what is on screen, including the home app.- On a B8 (webOS 4.4.3) there is no
com.webos.service.capture;com.webos.service.tv.capture/executeOneShottakes the same payload, answerscapturedWidth: 0and still writes the file, and its picture includes the HDMI video, which the C2's leaves black. luna-sendrun from an SSH shell can print nothing forcom.webos.applicationManagercalls, while the same call from a node child process answers.- The Web Browser (
com.webos.app.browser, 2.0.7) hidden withvisible: falsebound over itsappinfo.jsonno longer starts:launch, with or without a saved page'sparams.target, returns true and the system log hasNL_APP_LAUNCH_BEGINand nothing after it. Shown again, the same launch opens it. Other hidden LG apps (LG Channels, Media Discovery) still open.
Screen saver timing (webOS 5.6.2, CX; webOS 10.3.1, C5)¶
Both TVs were timed from the last key press to tvpower's Screen Saver
state, with a blank browser page (com.webos.app.browser, target:
about:blank) in front.
- The idle time is screenmanager's, not the compositor's.
com.webos.surfacemanager.userActivityTimeout(120000 ms) runs a timer inStarfishScreenSaverView.qml; when it ends,StarfishViewStateController.qmlcloses overlays, alerts, the keyboard, PIN prompts and the spinner. It does not start the screen saver. - CX:
/usr/sbin/screenmanagerreads configd'scom.webos.service.nop.screenSaverTimeout, in seconds. The base layer has 1800; thetvoverlaylayer sets 130 for OLED, and the screen saver came on 123 s after the blank page opened. Whether a value written there is used was not tried on the CX. - C5: screenmanager does not read that key (its value there is 180, and
60 written to it changed nothing, live or after a reboot). It subscribes to
settings
option.screenSaverTimer, in minutes, withcheckChangedScreenSaverTimerByUserbeside it (default, oruseronce LG's menu has set it). The allowed values are 3, 10, 20 and 30, and 3 timed at 176 to 181 s. 2 and 4 were stored (withvalueCheck: false, and again after adding them to the allowed list withsetSystemSettingDesc), but with either one stored no screen saver came at all, live, aftersystemctl restart screenmanager, or after a reboot. So only LG's four values work, and anything else switches the screen saver off.resetSystemSettingDescputs LG's list back. com.webos.service.screenmanager.screenSaverProperties(OLED layer:preferredType2 and 3,screenSaverDelay30) is per kind of screen saver request, not the idle time.- An input with no signal blocks it. Over HDMI 1 with nothing connected
(CX), or Live TV with no antenna (C5), no screen saver came in over 200 s.
On the CX the input shows its own No Signal picture instead, LG's No Signal
Image (settings
general.noSignalScreenSaver, on on that CX, off on the C5). - On the C5 the TV falls back to Live TV after a reboot, and when the
compositor's 120 s timer closes a Home window with nothing under it, sam
launches the last app (
LAUNCH_LASTAPP on_foreground_null). A Home that comes back that way closes the screen saver as it opens.
sam losing the screen saver app (webOS 9.2.2, C2)¶
On 2026-10-17 a C2 with a custom screen saver mounted over
com.webos.app.screensaver stopped starting it: tvpower's
turnOnScreenSaver returned true, nothing came up, and sam's getAppInfo for
the app answered errorCode 1, "Invalid appId specified OR Unsupported
Application Type", although its appinfo.json (QML) and files were in place,
nothing in profile.blockedAppList or blockedSystemAppList named it, and
listApps left it out. One configd nudge (profile.blockedAppList) brought it
back at once, and the screen saver then started. That morning had several
deploys, sam rereads after hiding and showing tiles, a remote keys filter
reload and a screen saver switch; none of these, repeated, lost it again, so
the cause is not known. Start screensaver now checks getAppInfo first and
rereads the apps where sam has lost it.
tvpower dropping a screen saver request (webOS 9.2.2, G3)¶
On 18 October 2026 a G3 answered turnOnScreenSaver with returnValue true and
started nothing. A getPowerState subscription showed processing: "Request
Screen Saver" and then "Screen On" 10 to 30 ms later, back to plain Active.
LG's own idle screen saver was refused the same way, at 180 s and again at
360 s with no key pressed. tvpower asks the clients in getClientList's
ListScreenSaverRequests before it starts one; on that G3 they were
com.webos.service.oledepl and com.webos.app.browser on /power, and
com.webos.service.screenmanager and netflix on /power2. A C2 on the same
webOS, where the request works, has the same list without Netflix, which it
does not have installed.
It was still refused with the browser and Netflix closed and gone from that list, leaving only oledepl and screenmanager, and with:
- every other app closed and nothing in
com.webos.media/getActivePipelinesorgetForegroundVideoWindow, - screenmanager restarted (
systemctl restart screenmanager), - LG's own Home back in its place and Native Tv stopped,
- Native Tv's ad blocking off and screenmanager restarted after it,
- settings
general.screenSaverEnabledwritten off and on again, - oledepl's
setPcScreenSaverResponseset toack: true(itsgetPcScreenSaverResponsehad read false).
screenmanager's strings name a server-sent app blacklist, full-screen playback,
a per-app manual mode (setScreenSaverMode), store mode, an unfinished first
use and a Hall sensor as reasons. Store mode was home,
/var/luna/preferences/ran-firstuse was in place, and nothing was playing.
Which client refused, and why, was not found: their debug logs do not reach
/var/log/messages, which PmLogDaemon filters by
/etc/PmLogDaemon/whitelist.txt, nor /var/log/legacy-log.
Launching com.webos.app.screensaver through sam still brought LG's screen
saver up, and closeByAppId closed it. tvpower stayed Active under it. The
app answers a key by calling tvpower's turnOnScreen and leaves closing it to
tvpower, which from Active refuses ("The current sub state must be 'screen
off'"), so the remote did not close it. Start screensaver launches the app
where tvpower drops the request, except over full-screen playback, tracks it
through sam's running list, and closes it on any key the remote-button
worker reads from /dev/input.
Home's snapshot (webOS 5.6.2, CX)¶
The webOS 9 entries above describe the home app's CRIU checkpoint. On a CX:
- sam restores only apps listed in
CRIUSupportAppsin/etc/palm/sam-conf-tv.json(Home and fullhome among them), and only while/tmp/criu_enableexists.criu.shcreates that flag at boot; with it moved aside, a killed Home starts fresh. The flag is not per app, so the other snapshot apps (the inputs and Live TV) are not restored either until it is back. - Deleting
/tmp/checkpoint/com.webos.app.homeis not enough: the next restore copies it again from/mnt/lg/cmn_data/checkpoint. Aninvalid_imgmarker in the tmpfs copy means "refresh from flash", not "skip". - Setting Home's
preloadModetofullin configd's preload list made no difference: Home was still restored (parameters.snapshot: true). - With no image in either place, sam logs
criu dump image is not exist, starts the app normally and dumps it about 0.25 s later. The dump comes after QML loads and beforeappLaunched, so a luna connection made at load time is dead after a restore (Denied method call). - A restore whose saved pid is taken still worked: libcriu restored with a
new pid (
enable_zygote:1). /etcis a read-only overlay on a full squashfs, sam readssam-conf-tv.jsononce about 5 s into boot, andsam.service'sExecStartPrescript kills every native app when sam is respawned, so the list cannot be changed without a mount and a sam restart at every boot.
Home's launch events (webOS 5.6.2, CX)¶
- At power-on,
com.webos.app.inputcommonlaunches the default home app withactivateType: powerOnwhen the TV was switched on by a key andgeneral.homeAutoLaunchis on (it is the Home Auto Launch switch in LG's settings). LG's home app closes itself about 9 s later on its own timer; nothing in the system does it. - Home gets
relaunchwithlaunchType: homeKeyfor a Home press andactivateType: recentfor a long press. The My Apps key sends the same launch as Home. Launching another app sends Homepausewith reasonkeepAlive; it never getsclose. - Home is an overlay window (
_WEBOS_WINDOW_TYPE_HOME), so the app beneath stays the foreground app and keeps playing. A Home window that sets_WEBOS_WINDOW_TYPE_CARDbefore it shows becomes the foreground app, and the app beneath getsbackgroundand gives up its media pipelines.
The default home app (webOS 10.3.1, C5)¶
- Which app the Home key opens is settings
general.defaultApps(home), set withapplicationManager/setDefaultApp { category: "home", appId }. The surface manager callslaunchDefaultAppwith{ activateType: "home"|"myapps", launchType: "homeKey" }. - If that app is gone, the Home key does nothing ("no default app is set for the category"), while power-on still opens LG's home.
- A developer-mode QML app runs under
qml-runnerwith onlypublicpermissions, and its luna calls never reach the bus, so a separate app cannot stand in for Home.
Native Tv Home on webOS 10 (G5, webOS 10.3.1)¶
- LG's Home's
appinfo.jsondeclares"appCategory": ["home"]. sam answerslaunchDefaultApp { category: "home" }with the app that declares it, withdefaultApps.homeunset too. A web app mounted under the same id without it gets "no default app is set for the category", whateverdefaultApps.homenames, and the Home button does nothing: surface-manager logs the press (NL_RCU_CONTROL_USE, key 773) and launches nothing. With the field, Home from live TV had the app on screen 0.09 s after the press. systemUi.js'shandleHomeKeyskeeps the press, sets a 2.5 s long-press timer, and on a release before it sends Home to the focused window again and launches the default home app on that pass. Held for the 2.5 s, it opens the screen magnifier (KEY_SCREEN_MAGNIFICATION, zoom 150) instead.- sam took the changed manifest on a block and release of
com.webos.app.homewithin the second; the blocked-app list nudge never took ("sam had not caught up"). - The TV has no
/etc/issue./etc/starfish-releasehasRockhopper release 10.3.1-3006, and/etc/os-releaseVERSION_ID=10.3.1.
What the TV opens as it starts (G5, webOS 10.3.1)¶
Measured on 19 October 2026 on an OLED55G56LS, Quick Start+ off.
- Every power-on is a cold start with Quick Start+ off. The kernel
restores a prebuilt snapshot (
/proc/cmdlinehassnapshot resume=...,bootd.log--Snapshot=YES), and/proc/uptimerestarts at each power-on from standby. The power-on is handled about 10 s in. - bootd chooses the first app. It reads
/etc/palm/action-condition.json(com.webos.bootManager.actionConditionConfPathunset): theInput Appaction launches the last input (physicalLastInputAppin/var/luna/preferences/general, Live TV by default). Withgeneral.homeAutoLaunchonand a power-on reason incom.webos.service.tvpower.fullHomeBootingPowerOnReasons(aiKey,lastPowerOn,localKey,remoteKey,seniorHelp), it shows its boot logo (com.webos.app.bootlogo, 10.6 to 16.8 s) and launchescom.webos.app.homewith{"boot": true}at 14.2 s; LG's Home loggedNL_HOME_SHOWN(launch_typebootingHome) at 15.5 s. - With it
off, LG's Home never comes to the front. On the remote, bootd loggedhomeAutoLaunch(off), showed no boot logo and had Live TV in front at 14.2 s; nothing launchedcom.webos.app.homeuntilcom.webos.service.preloadmanagerpreloaded it at 67 s, after the boot hook had mounted Native Tv Home over it. - A restart from the menu or
rebootismicomPower. Not in the list: withhomeAutoLaunchon, bootd still put Live TV in front at 14.9 s. - Writing
homeAutoLaunchthrough the settings service turnscheckHomeAutoLaunchValuefromdefaulttouser. - bootd logs the app it put in front as
BootSequencer) '<id>' is foregroundin/var/log/bootd.log, which is on tmpfs and holds the current boot only. - The boot hook ran 31 to 36 s in. Mounting and rereading took 8 s with
LG's Home running in front, 1 to 2 s with it never
started, and 10 s once. sam's
last_input_handlerrelaunched Home 1 s after the hook stopped LG's Home in front, with nothing in front in between. - Wake-on-LAN did not wake it from
Power Offafter apowerOff, on either interface, withnetwork.wolwowlOnOfftrue. - With Quick Start+ off it powers off 4 to 6 s after Active Standby, so
a
powerOn6 s after apowerOfffound it gone. - With Quick Start+ on, a
powerOffwent to Suspend 5 s after Active Standby (PowerOffReasonoslbSaving). Woken by the remote from Suspend, uptime carried on and the mount was still in place; bootd loggedhomeAutoLaunch(on), launchedcom.webos.app.home, and Native Tv Home was in front 0.76 s later.
What the TV opens as it starts (G3, webOS 9.2.2)¶
Measured on 19 October 2026 on an OLED55G36LA.
- With Quick Start+ on, a wake runs bootd too. Woken by the remote from
Suspend, it logged
homeAutoLaunch(on)and launchedcom.webos.app.homewith{"boot": true}: Native Tv Home, still mounted, in front 1.3 s later. With auto launchoff, bootd put the last input (HDMI 4) in front instead. - Wake-on-LAN is
wakeOnLan, and bootd stayed on HDMI 4 with auto launchon. fullHomeBootingPowerOnReasonsis missing (missingConfigs); bootd opened Home onremoteKeyand not onmicomPower.- A cold start logs the first app as on the G5:
'com.webos.app.hdmi4' is foregroundat 13.4 s, afterremoteKeyat 9 s. - Off and on again 6 s apart goes Active, Active Standby, Active, with no boot: bootd runs and puts the last input in front, and the boot hook does not run.
- The settings service gave no
quickStartModefor agetSystemSettingsquickStartModesent as the TV woke from Active Standby, twice; read seconds later it answered. powerOnwith{"reason": "remoteKey"}, sent over SSH in Active Standby, wakes it as the remote does: tvpower and bootd logremoteKey.- Writing
homeAutoLaunchleftcheckHomeAutoLaunchValueatdefault, unlike the G5. - With Native Tv Home first, the boot hook started 30 s in and had it in place at 34 to 39 s, the screen saver mount after it.
What starts the boot hook, and when (B3, webOS 10.3.2)¶
Measured on 20 October 2026 on an OLED65B3PUA with the Homebrew Channel, over
one cold start. Seconds are after power-on; bootd's clock reads about 1.4 s
ahead of /proc/uptime.
| s | |
|---|---|
| 19.3 | bootd: core-boot-done |
| ~23 | devmode.service starts |
| 24.4, 25.7 | init-boot-done, minimal-boot-done |
| 39 | the Homebrew Channel's service process starts (its start time in /proc) |
| ~43 | /tmp/webosbrew_startup is touched: startup.sh runs |
| 46.7 | init.d hooks start, after the script's sleep 2 |
| 56.6 | the Native Tv server is listening |
| 58.0, 69.0 | rest-boot-done, boot-done |
- The trigger is not
devmode.service, and not the Activity Manager. The Homebrew Channel's source (services/service.ts) registers an activity that waits forcore-boot-doneand calls the service's/autostart, which spawnsstartup.sh;/tmp/webosbrew_startupmakes a second trigger harmless. But theactivitymanagerprocess on this TV started at 58 s, withrest-boot-done, 19 s after the service process (39 s), so that activity did not start it. The installed app is 0.7.3, whoseappinfo.jsonhaspreviewMetadata.targetEndpointset to the same/autostart: LG's launcher asking an app for its preview is the likely caller. Not shown: no log names the caller. start-devmode.shdoes not exist on this TV, so LG'sdevmode.shruns nothing from it, and/media/developerhas 214 files, so itschmod -R 777costs nothing.- About 20 s pass between
core-boot-doneand the service process starting, and none of the Homebrew Channel's code runs in them: whatever calls the service waits on LG, under a load average near 32 on 4 cores.startup.shfollows 4 s later. On a G5 (webOS 10.3.1) the same step took 12 s: the service at 22.9 s aftercore-boot-doneat 10.7 s (boot-speed notes). - Process start times (s):
ls-hubd1,bootd2,sam7, the firstWebAppMgr24,activitymanager58. In webOS OSE the Activity Manager is inwebos-rbd.target, started atrest-boot-done; LG's build matches that here. rest-boot-donecame 1.5 s after Native Tv Home came to the front (56.5 s). bootd may wait on a Home in front before it emitsrest-boot-doneandboot-done, in which case the hook delays them. Not tested; one start with the Home open at boot switched off would show it.startup.shruns theinit.dhooks one after another and clears its failsafe flag 10 s after the last. A hook that waits holds up the later ones and the flag. A start before the flag clears makes the next boot skip every hook (issue 88).
What can be changed, and what it saves, with the server at 56.6 s:
- Start the server first and detached in
50-tvweb: up to 8-9 s. The hook waits through the toast, the takeover and the Home open before it starts the server, and keeps a 5 s buffer so the server does not contend with the rest of boot, which has to be measured. Measured on 21 October 2026: with the services hook's systemd reload (8.6 s) run alongside the takeover the server was listening at 62.9 s; with the reload held back 30 s and the 5 s buffer dropped, at 53.8 s (takeover 7.4 s instead of 9 s, server listening 0.9 s after it started). The reload then finished at 80.5 s. - Edit
/var/lib/webosbrew/startup.shto drop thesleep 2: about 2 s. The Homebrew Channel keeps a modified copy and flags it, and stops updating it. - Running the hook from LG's
start-devmode.sh: the only way into the 20 s, and closed unless LG'sdevmode.shdoes not check its signature. Where it does, a bad file turns developer mode off and removes/media/developer, with the Homebrew Channel in it.devmode.shis read-only; read it foropenssl dgstbefore considering this. - LG's boot lists and systemd units are on the read-only rootfs, and a
filesystem overlay is itself applied from
init.d(overlays), so none fires before the chain it would speed up.
Changes to writable files alone put the server near 47-52 s. What the launcher needs before it asks for the preview is the open question: the G5's service started at 22.9 s, 16 s sooner than this B3's.
A splash during the cold start (B3, webOS 10.3.2)¶
Measured on 21 October 2026, seconds after power-on, from bootd's "is foreground" lines.
- A web app launched at 21.7 s drew at 43.8 s. It waits for WebAppMgr, whose first process starts at 24 s, under a load average near 33.
- A QML app launched at the key filter's first config read (about 17.5 s)
was in front at 21.0 s.
qml-runnerdoes not wait for WebAppMgr; sam accepts an unsigned"type": "qml"app from/media/developer/apps. - bootd puts the input in front at 21.6-22.3 s whatever is running, a launch in the same instant losing to it. The filter opens the splash again 1.5 s after the input is in front, and it stayed in front from 23.2 s. The input shows for about 1.6 s.
- bootd takes the first app from
lastInputApp/physicalLastInputApp. Its log showsRespawn) foregroundAppId:andBootSequencer) '<id>' is foregroundfor the splash at 20.98 s and forcom.webos.app.hdmi4at 21.57 s, andcom.webos.app.inputcommonis asked forhdmi4throughchangeRunningAppIdat 19.6 s. Naming the splash in those two settings would start the TV on it with no input shown; not done, as they are the TV's last-input memory (what Back and a wake open) and an earlier build that set them for Native Tv Home had to be cleaned up after. - Naming the splash there starts the TV on black, not on the splash. With
lastInputAppalone set tocom.tvweb.splash, bootd still readhdmi4and both keys readhdmi4again after the reboot. With both set, bootd launched it throughcom.webos.app.inputcommonat 19.7 s andcom.tvweb.splashwas in front from 25.9 s with no input shown, but sam gave it inputcommon's process (appTypenative_qml, noqml-runnerrunning): the screen was black and stayed so, as the QML app's own close after 100 s never ran. - The relaunch 0.5 s after the input (
lib/remotekeys.js), not 1.5 s, left the input in front 0.05-0.18 s, and delayed WebAppMgr by 10 s: afterfirstapp-launchedbootd waits up to 15 s forbanner-readybeforeSIGNAL_init-boot-done, andwebapp-mgr.service(wanted bywebos-ibd.target) starts after it. inputcommon sendsbanner-readythroughcom.webos.bootManager/generateSignalwhen it shows its input banner (BannerInterfaces.qml), which the splash now covers first; bootd loggedEvent (banner-ready) timeout is doneand init-boot-done at 36.0 s on two boots, against 25-27 s.generateSignaltakes any name from a rootluna-send. - Sent by the boot hook at 22.6 s,
banner-readybroughtSIGNAL_init-boot-doneat once and WebAppMgr's process at 22.9 s. systemd called it active at 36.4 s, before it had drawn Native Tv Home (launched at 30.3 s), and with the server started then Home was in front at 48.6 s. - Hardware of this TV: four Cortex-A55 at one fixed 1156 MHz step, 1.7 GB to Linux, 600 MB swap, PowerVR GPU (b3.md). The load average near 33 is not CPU work: 31 of LG's driver threads sit in uninterruptible sleep, booted or not, and a booted TV playing Netflix at a load average of 32 had its CPU 26% busy.
- The compositor's
console.warnoutput is not in any file or in journald (journalctlhere has no-g), so a filter's behaviour is read from bootd's lines andgetForegroundAppInfo.
Running our own code early in a cold start (B3, webOS 10.3.2)¶
Measured on 21 October 2026, seconds after power-on.
- The Homebrew Channel's service cannot be called from the key filter. The
filter calls the bus as
com.webos.starfish.keyfilters, whose role (com.webos.surfacemanager.role.json) lets it call onlycom.lge.*,com.palm.*,com.webos.*,airplay.serviceandocp.service.org.webosbrew.hbchannel.serviceis outside that, so the call is dropped with no reply, however often it is repeated; a call totvpowerin the same run is answered. - A bus service of ours under
com.webos.*is reachable. Declared in/var/luna-service2-dev(the directory the Homebrew Channel's own files are in), with a role naming bothcom.webos.surfacemanager*andcom.webos.starfish.keyfilters*as callers,ls-hubdstarts itsExecas root on the filter's call. The API had to be in thepublicgroup: a group of its own, granted to the compositor through a developer package'sclient-permissionsfile, gave no reply in 80 s. The role is then the restriction, and a call from a shell is refused ("Not permitted to send"). - The bus is not ready at the filter's first config read. The first call to get through was the third, about 2 s after the first (the filter goes live at 17.5-19.7 s, and the script first ran at 21.7-22.8 s). One try a second until about 33 s, the service running once per boot, covers it.
startup.shran at 41-43 s on the same boots, so the earliest point for a script of ours moved from about 43 s to about 22 s.- Starting the boot hook at 23 s, the Home takeover finished at 27.4 s,
not 52-57 s: sam reported the new Home as
webon its first poll at 26 s, and the rest of the old 26 s waslg_home_pids, a loop over every process in/procwith two forks each, which took 26 s at a load average near 33. Reading only theflutter-clientprocesses (pidof) took 1 s. The server then started at 29.9 s and listened at 35.8 s, against 53-63 s before; LG's own boot signals did not move (core-boot-done19.9 s,rest-boot-done54 s,boot-done67 s). - A
systemctl daemon-reloadafter/tmp/boot-donerestarts WebAppMgr.lsm-ready.pathwatches/tmp/lsm-ready, which exists from 16.8 s; a reload makes systemd startlsm-ready.targetagain, andlsm-ready.service(condition:/tmp/boot-done) runssystemctl stopandstartonwebapp-mgr.service,boosterandmaliit-server. A reload before boot-done (a B3: one at 58 s) is skipped by the condition; the services hook's at 94 s, 12 s long, stopped WebAppMgr at 94.5 s, took Native Tv Home off the screen and had LG'slast_input_handleropen it again at 97 s. A reload run by hand on a booted TV did not restart it. LG's Home on webOS 10 is Flutter, so the restart goes unseen there. - The server's start slows WebAppMgr's. Three SSH-reboot boots each way,
alternated, with the early start: with the server started at about 29 s,
webapp-mgr.servicewas active at 47.8, 54.2 and 46.6 s and the server listening at 34.6-36.6 s; with the server held until WebAppMgr was active, WebAppMgr was active at 38.5, 34.7 and 39.2 s and the server listening at 39.1-43.4 s. WebAppMgr's process started at 24-27 s either way. - WebAppMgr draws before systemd calls it active. On a remote power-on
with the server held, its process started at 36.2 s, Native Tv Home was in
front at 46.0 s and
webapp-mgr.serviceactive at 55.6 s; with the server running alongside (an earlier boot), it took 21 s from its start to Home in front.
Muting and pausing (webOS 5.6.2, CX)¶
com.webos.audio/setMutedonly changes audiod's own status: the TV keeps playing andcom.webos.service.apiadapter/audio/getMutestays false.apiadapter/audio/setMute { mute }mutes it and shows LG's mute icon. Switching on from standby, or a reboot, clears the mute.- With sound through an ARC soundbar (
external_arc),com.webos.audio/setVolumeleft the volume as it was. Not looked into further. com.webos.service.networkinput/controls/pausepaused a playing video in YouTube, Netflix, Apple TV and Peacock. Paramount+ only shows its player bar on the first one and pauses on the second. On YouTube's browse screen it does nothing.applicationManager/pause { id }sends the apppausebut leaves it the foreground app; YouTube stopped, and alaunchafterwards left it on a black screen for over 25 s.com.webos.media/pausefails on an app's own pipelines (is_managed: false).
The system log (webOS 5.6.2, CX; webOS 10.3.1, C5)¶
- On the CX,
/var/log/messagesgets only theNL_*messages named in/etc/PmLogDaemon/whitelist.txt. A context raised to debug withPmLogCtlwrites nothing more there, and a native app's stdio is/dev/null. - The C5 keeps its system log in
/var/log/dbg-logas well as/var/log/messages; QML errors are in the first.
ls-monitor restarts the TV (webOS 10.3.1, C5)¶
Running ls-monitor on the C5 made ls-hubd open a monitor socket per
service until it ran out of file handles (Too many open files, about 360 in
use normally, limit 1024). faultmanager recorded fd leak is happened on
"process = ls-hubd" in /var/spool/faultmanager and answered the next
suspend request with rebootToSuspend, so the TV restarted with
PowerOnReason: rebootByFault at its next standby. It happened both times
ls-monitor was run, and not without it.
Consent flags on a CX and a C5 (webOS 5.6.2 and 10.3.1)¶
How the flags are rebuilt from the agreement documents is described in IMPLEMENTATION.md; this is what two more firmwares showed.
- Which flags exist. Two CX on the same firmware and a C5 all have
acrAdAllowed,acrAllowed,acrGdprAllowed,acrOnAllowed,additional1Allowed,additionalDataAllowed,cookiesAllowed,customAdAllowed,customadsAllowed,generalTermsAllowed,marketingOnAllowed,networkAllowed,remoteDiagAllowed,thirdPartySharingAllowed,voiceAllowedandvoice2Allowed. Only the C5 hasadditional2Allowedandadditional3Allowed; only the CX havetakeOnAllowed.shoppingOnAllowedwas on the C5 and one of the two CX, so the same firmware can differ. - What rests on what.
generalTermsAllowedrests onS_SVC(Terms of Use) andS_PRG(Privacy Policy); on the C5 so doesadditional3Allowed.networkAllowedrests on no document. - A flag written off with its documents left accepted comes back at boot.
With every flag written off on its own, a reboot of all three put
generalTermsAllowedback on, andadditional3Allowedon the C5. All the others,networkAllowedamong them, stayed off. networkAllowedoff stops nothing visible: on a CX with it off, YouTube and Netflix opened to their profile screens and the Content Store listed apps, with some pictures missing. It held through a reboot on all three.- The Terms gate (CX). With
S_SVC,S_PRGor both withdrawn, the TV setgeneralTermsAllowedoff at its next boot, and then YouTube, Netflix and the Content Store each openedcom.webos.app.eula(LG's User Agreements screen) instead, on six of nine launches; the Home key on it asked whether to end User Agreements. With both accepted and the flag written off, launches were blocked at once. Accepting both again and setting the flag opened the apps without a restart. So the gate is the flag, which the TV sets at boot only when both documents are accepted.chpAllowedwent off with the terms and stayed off after they came back. general.launchEulaByHomewas already false on a CX and the C5; on the C5 only the first-use app names it. Not tried.
Privacy settings and what reads them (webOS 10.3.1, C5)¶
Readers were found by searching /usr and /etc for each key, so a reader
that builds the name at run time would be missed.
| Key | C5 value | Read by | Effect found |
|---|---|---|---|
option.dbgLogUpload |
true | uploadd, PmLogDaemon |
Not in LG's menus (ui.visible: false). Once seen back on after a boot, with uploadd running 73 s in although its unit had been masked under /run. |
option.faultLogUpload |
false | uploadd, remotediag, prosense, PmLogDaemon, Settings, first use |
Its description limits it to KOR, USA. |
option.usageCare |
true | Settings only | The Usage Care menu entry, which opens Family Care. Family Care's own code never reads it; its screen-time lock reads the parentalControl keys, and it has no network code. |
option.thirdPartyCookie |
on |
the HbbTV plugin of WebAppMgr, Settings | HbbTV only. Values on, off, onByUser, offByUser. |
general.voiceLongDistance |
on | voiceinput |
Off or on, no capture device was opened in Active or Active Standby; detection may run on the sound chip, so not settled. |
option.watchedListCollection |
on |
none found (only tvdataexchanger/spec.xml names it) |
Unknown. |
The CX has voiceLongDistance and watchedListCollection but none of the
other four. On both, general.lmt (Limit Ad Tracking) read on; the
advertising ID read limitTracking: true only after a reboot, while the
advertising service had not answered before it.
Others with no effect found:
option.webOSPromotionVideo(on/off): nothing outside LG's settings definitions names it, on either TV.general.homeAutoLaunchMode(full) on the CX: no reader found.general.powerOnScreentakes onlytodaysandliveTv, and only the broadcast service (legacy-broadcast) reads it.hotelMode.enablePowerOnDefaultVolumeandpowerOnDefaultVolumeare set by LG's installation menu together with hotel mode itself. On the C5audiodreads the first; on the CX nothing outside that menu does. Not tried.
LG host names in the firmware (webOS 5.6.2, CX; webOS 10.3.1, C5)¶
A search of /usr and /etc for names under lgtvcommon, nextlgsdp,
lgtviot, lgthinq, ngfts, wiselg, lggalleryplus and lgsmartad. None
of these was seen in a network capture; they are only what the firmware can
name.
- Region prefixes. Many names appear bare and with
aic.,eic.,eu.,kic.andus.in front (cdpbeacon,cdpsvcandwauunderlgtvcommon.com,info.lgsmartad.com), or asaic-,eic-,kic-andqt2-forms (ngfts.lge.com, thelgthinq.comservices). A hosts entry blocks only the exact name, so the prefixed forms need their own lines. - Names held with a leading dot:
.api.lgtviot.comand.lgtviot.comon the CX,.lgtviot.com,.buddy.lgtviot.comand.pnv.lgtvcommon.comon the C5, which suggests the firmware puts a prefix in front at run time. Not confirmed. - CX only:
fooddelivery,cpvandqt2-kic.imagesvcunderlgtvcommon.com. C5 only: thenextlgsdp.comnames (ibs,ibsstat,rdx2,qt2-US),dev-ruc-ngfts.tv.wiselg.com, andcpauth,qcardservice,rdl,wiseconfig,wiseresourceandvideoadsunderlgtvcommon.com. - Both:
nudge,recommend,rdx,homeprv,netflixvoiceandvideoacrunderlgtvcommon.com;api,pushandsportsunderlgtviot.com;ad,infounderlgsmartad.com. - No
lggalleryplus.comin either.
ACR on a CX (webOS 5.6.2)¶
acr2starts on demand. Its D-Bus service file isType=dynamic, so any call tocom.webos.service.acr, such as a status query, starts it. A runningacr2is not a sign ACR is on. Idle, it used 0.08 s of CPU in about 15 minutes, 3.5 MB, and only bus sockets, withlibvtcapturemapped and the Alphonso library (libalphonsosolution.so) not.- What starts it on a stock TV. The activity manager's
/etc/palm/activities/com.webos.service.acr/activity-com.webos.service.acr.start.json("Start ACR service when TV on") callsacr/startAcroncebootManager/getBootStatusreportsrest-boot-done. LG's input app (com.webos.app.inputcommon) and thecom.webos.app.acr*apps call the service as well; in/usr/sbinonlylivepick-plusnames it. - With Live Plus off it does not stay running after boot. On a CX with
livePlusoff and the ACR consents off,acr2was not running 15 hours after boot, and its data folder has no record of a run. Its strings include aQuitpath, the eula check it logs (generalTerms,livePlus,IBA,DPA), and an activityacr_wake_up_by_liveplus_on("ACR service as dynamic for live plus menu"), which reads as a trigger to start it again when Live Plus is switched on. That it ran and quit was not seen: the activity list was not readable and nothing was logged. - Started by a call, it stays. On the same CX a single
getACRSolutionStatusstarted it (answerACRSolutionStatus: false), and it was still running 5 minutes 20 seconds later: no CPU time, 3.5 MB, 8 sockets, no/tmp/acr.xml. A SIGTERM ended it, and nothing started it again within 30 s. So a status query undoes what switching Live Plus off achieves until the next reboot; Native Tv's Privacy panel asks it only while it runs. - Started that way, it collects nothing. With Live Plus and
acrOnAllowedoff, anacr2started bygetACRSolutionStatuswas watched for 2 minutes: no CPU time, 5 threads throughout,libvtcapturemapped and the Alphonso library not, no network sockets (8 local bus sockets), no/tmp/acr.xml,getVideoCaptureStatusstoppedwithcaptureSpeed0, andACRSolutionStatusfalse at the start and the end. /tmp/acr.xmlis a downloaded configuration, not a switch. Its strings inacr2are "[Configuration] Initialize : downloading config file", with/mnt/lg/cmn_data/acr.xmlas a fallback that does not exist. On a CX and the C5 it readACR_On="true", audio capture andsend_datatrue while ACR reported itself stopped. Rewritten to false, it was true again about 30 s later and stayed false after a second rewrite; what wrote it back was not found. It was gone after a reboot on the CX, and still there on the C5.- ACR switched on (
livePluson,acrOnAllowedon) changed nothing in 3 minutes: no Alphonso library loaded,getACRSolutionStatusfalse, capture stopped, no network sockets, no/tmp/acr.xml. No input had a signal. - Why it went no further: traced over a restart of
acr2, it reads the country,eulaStatus,livePlus, the device name, sdxgetServer(Production) andgetPublishFlag(true), then askscom.webos.service.sdx/getDeviceAuthenticationStatus, getsisDeviceAuthenticated: false, provisioningCompleted: false, and stops. Whether that was the network consent being off, the hosts block, or both was not tested. /etc/pmlog.d/acr.confpoints theacrcontext at/var/log/acr.log, which is never created; even at debug level nothing reached/var/log/messages.
Background services the bus hub launches (webOS 10.3.2, B3)¶
Running in ls-hubd.service's cgroup, so launched by the hub on a call rather
than by a unit of their own: livepick-plus, admanager, sportsalarm,
iot-client, com.webos.service.buddyconnector, lg.thinqai.adapter and
com.webos.service.familycare (an iotjs script). com.webos.service.pushclient
and ocpservice (ocp.service) have units. Over 20 s none used measurable
CPU or held an internet connection; together they took about 48 MB. The names
in their strings: aic-ngfts.lge.com (livepick-plus), push.lgtviot.com
(sportsalarm), ocp.lgtviot.com (ocpservice), api.lgtviot.com,
connect-client.lgthinq.com and common.lgthinq.com (iot-client),
info.lgsmartad.com (admanager). Casting goes through other services:
com.webos.chromecast.cell, airplay, miracast, dmr, and DIAL, which is
the node service ss.gateway in /usr/palm/services/com.webos.service.dial.
Cold start: snapshot boot (webOS 10.3.2, B3)¶
The kernel command line has snapshot resume=/dev/mmcblk0p53, and after a
power-on or a reboot /sys/power/mode reads resume: the TV resumes a
hibernation image taken partway through an earlier boot, made by
/usr/sbin/snapshot-boot-manager (snapshot-boot-on.service) once the
processes in /etc/snapshot/snap_list (configd, surface-manager, tv, audiod
and others) have connected to it. Everything up to about 13.5 s of uptime comes
from the image: systemd-analyze charges snapshot-boot-on 15.6 s and puts
the compositor at 3.7 s, neither paid at power-on. Timed from another machine,
a reboot reached bootd's start about 5-6 s after the reset and the last input
(HDMI) was shown at about 22.5 s of uptime, about 14.5 s after the reset; with
the power-on reason remoteKey, bootd asks SAM for listLaunchPoints first
(5 s) and Home is shown at about 25.5 s. Later stages wait on
/usr/bin/resourcemon (/etc/palm/bootd.json: CPU under 50 %, 30 s
timeout): rest-boot-done came at its timeout, 56-57 s, with the CPU at 65-93 %
from 45 to 70 s. After boot the preload manager launches its apps one by one
from about 60 s (/var/preferences/webos-preload-manager-conf.json holds the
TV's own choices).
The first code of ours to run is the compositor's key filter, at its first
config read (about 17.5 s); a bus service in /var/luna-service2-dev can be
called from about 18.7 s, when snapshot-boot-resume.service runs
ls-control scan-volatile-dirs. A service there with the name of a system
service does not take its place: the hub still runs the system one. Started
before that, and so only stopped: remotelogger (inside the image) and
com.webos.service.pushclient (16.8 s).
lg.thinqai.adapter is run as jailer -t native_mvpd -i lg.thinqai.adapter -p
/usr /usr/sbin/lg.thinqai.adapter. The jail's /usr is an overlay of the
read-only /usr, which a bind mount on /usr/sbin does not show through.
jailer sets the jail up at the program's first launch (about 32 s) and reuses
it after, so it can be set up beforehand with /bin/true and the program in it
bound over. Setting it up took about 7 s at 22 s into a cold start; at nice 10
the whole services hook took 15 s.
ss.gateway, the node process of about 36 MB, is DIAL
(com.webos.service.dial), not the second-screen gateway
(com.webos.service.secondscreen.gateway), which xinetd starts on a
connection to port 3000. iconnectivity (com.webos.service.ics) is UEI
QuickSet: Universal Control, recognising connected set-top boxes and soundbars
by CEC and HDMI infoframes, and smart lights. pbs is
com.webos.service.pbsw, the online programme guide and channel map for LG
Channels, Pluto and the live TV guide.
LG's other privacy daemons with the consents off (webOS 5.6.2, CX)¶
On a CX with every ad, voice, diagnostics and marketing consent off,
acr2 is the only one of these that the consents keep from running. The
others start whatever the consents say, and sit idle:
| Daemon | Started by | After 16 hours |
|---|---|---|
admanager |
activity com.webos.service.admanager.start: admanager/start once connectionmanager reports the internet up; also on demand (Type=dynamic) |
running, 1 s CPU |
adoverlay-service |
activity com.webos.service.adoverlay.start: startAdoverlay at rest-boot-done; also on demand |
running, under 1 s CPU |
livepick-plus |
activity com.webos.service.livepickplus.start: livepickplus/wakeup once the internet is up |
running, 1 s CPU |
voiceinput, voiceconductor, nlpmanager |
systemd units | running; 14 s, 1 s and 42 s CPU |
None had a network socket open. None of their start activities names a
consent, so there is no consent to switch off that stops them; what keeps
uploadd, rdxd, nudge, contentminer and remotelogger stopped is
Native Tv's background services switch, which masks their units.
Native Tv calls only admanager (the advertising ID, its reset and cookies)
and voiceinput.sound (the microphone switch), and asks either only while
it runs.
The microphone switch (webOS 10.3.1, C5)¶
The C5 has a far-field microphone (tv.model.supportFarFieldVoice: "on with
switch"; WoV PDM Mic on ALSA card 1) and a switch for it on the TV.
voiceinput.sound/getMicSwitchStatus reads the switch as a GPIO level:
high is on, low off. Flipping it off logged "MIC SWITCH Status Changed:
1 -> 0", took ThinQ's voice activation off with reason "Mic Switch", and
showed a toast saying the microphone is off. Before the flip, in Active
Standby, voice activation was already off with reason tvPowerState, so
wake-word listening does not run in standby.
Opening LG's Search with a query (B3, webOS 10.3.2)¶
Tried on 21 October 2026, to open a title from Native Tv Home's feed in
LG's Search. com.webos.app.voice reads its launch parameters in
qml/InputManager/InputManager.qml (handleLaunchParams): an activateType
(search by default) and, for a search, params.text and params.category.
Launched cold, with Search closed first, as
{"activateType":"search","params":{"text":"Crystal Lake"}}, and launched
with {"query":"..."}, it opened with the keyboard and an empty field both
times: the text is not filled in from a launch. params.keyword is read only
on the way to LG's browser (launchBeanBrowserByKeyword).
Compositor resolution and reported DPR (B3, webOS 10.3.2)¶
Checked on 25 October 2026 on the OLED65B3PUA, firmware 33.31.75, with production
Home and the standalone renderer reference loaded in the inspectable dashboard
app. With device-metrics overrides cleared, both pages reported 1920×1080 and
devicePixelRatio 2, but normal captures were 1920×1080 and
cc::LayerTreeHostImpl snapshots recorded device_viewport_size 1920×1080.
The production Home trace's active tiles had contents_scale 1.
Requesting deviceScaleFactor 2 through DevTools produced a 3840×2160 capture, while the reference compositor trace still recorded a 1920×1080 viewport and raster scale 1. That capture does not prove that the timed UI rendered at 4K. The earlier inference of 4K from reported DPR was incorrect on this TV.
The WAM source calculates reported DPR from hardware dimensions divided by app dimensions; that explains how a UHD panel and a 1080p app can report 2. A renderer experiment validated compositor snapshots before timing. Its verified 1080p reference and native workload both approach 60 Hz. Other firmware has not been checked with this method.
Luna and file shapes the native daemon met on a B3 (webOS 10.3.2)¶
Checked on 28 October 2026 on the OLED65B3PUA, firmware 33.31.75, by running the native daemon beside the Node server and comparing every read-only route.
com.webos.service.panelcontroller/getPanelUsageTimeanswers{}with "Failed to validate against schema: Missing mandatory field: 'subscribe'"; it needs{"subscribe": false}. It returnspanelUsageTimeas a number (34421 units of 10 minutes).com.webos.service.tv.systemproperty/getSystemPropertiesrefuses the keyspanelUsageTimeandlastCompensationTimestamp(ERROR_06, "Invalid argument");modelNameworks.tv.model.logoLightis refused too.com.webos.service.tv.displaydoes not exist (clear panel noise, dimming and light sensor reads all fail with "Service does not exist")./var/luna/preferences/eulakeeps the consent flags (acrAllowed, ...) undereulaStatus, besideeulaInfoandeulaInfoNetwork; none are at the top level.luna-sendprints nothing, with exit status 0, when it gives up after-w 2000on a loaded TV (a Cobalt app held the load average at about 33), so an empty reply is a timeout, not an empty answer.
What the B3's GPU costs (B3, webOS 10.3.2)¶
Measured on 29 October 2026 on the OLED65B3PUA (PowerVR B-Series BXE-4-32, OpenGL
ES 3.2 behind a GLES 2 context, 1920x1080, load average 32) by drawing one
frame again and again with a glFinish after each draw
(NATIVETV_DEBUG_BENCH, testing.md).
- An empty frame (clear, finish) takes 1.3 ms.
- A full-screen layer costs 0.9 ms as a blended flat colour or gradient and 1 to 1.3 ms as one picture. Eight opaque layers with blending off cost 0.1 ms each, because hidden surface removal shades only the last.
- The distance field (rounded corners, smoothstep edge, ring and inner band) costs 10 ms per full-screen layer, about 5 ns a pixel and eleven times a flat fill. Home drew seven such layers behind the cards, 62 ms of a 73 ms frame. Cheaper edge maths (a linear ramp, an early out inside, mediump) moved it by less than the run-to-run noise of a frame (0.7 ms).
- Choosing a texture per pixel with an
ifchain aroundtexture2Dmakes the compiler sample every slot (it needs the derivatives): the full-screen picture cost 3.4 ms against 1.3 ms for a draw with one texture. Level zero throughtexture2DLodEXT, which the driver offers, lets the chain branch and took another 1.2 ms off a frame of cards. - A draw call costs 0.03 ms (forty chained draws, 1.2 ms), so more draws are cheap beside the pixels they save. A viewport of half the size costs a quarter.
- The swap interval changed from 2 to 1 gives the first frame afterwards two
display periods (34 ms);
eglSwapBuffersat interval 1 blocks until the display and the loop's own sleep paces a 30 fps ambient frame (intervals 36 ms on average). About once in seven seconds the first GL call of a frame (glClear) blocks for 21 ms whatever the frame holds (the 2-draw splash does it too), which shows as one 35 ms interval. - Wake-ups under the load average of 32 arrive late: swap returns 14 to 19 ms
apart at normal priority (p95 18.4 ms), 15 to 18 ms at
nice -10(17.5 ms); the client raises its own priority and a root jailer permits it.