RDKEAPPRT-870, RDKEAPPRT-749: Optimize the RCU Pairing sequence and limit the scan activity to page level#223
Conversation
RDKEAPPRT-844,843 My Apps tile icons update offline/online state only…
There was a problem hiding this comment.
Pull request overview
This PR aims to optimize the RCU pairing flow by scoping Bluetooth/RemoteControl scan & pairing activity to the active page lifecycle, reducing background activity and improving teardown behavior.
Changes:
- Bluetooth splash pairing: track/dispose Thunder event listeners, prevent duplicate pairing setup, and stop pairing/scan work on page deactivation.
- SplashScreen AutoRemotePair: store timeouts/animation handles on
thisand clean them up on state exit (including stopping scan). - RCInformationScreen: add a pairing status UI, introduce a retry/timeout-based pairing loop, and stop pairing activity on screen deactivation.
- Bump app version to
6.0.25.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 8 comments.
| File | Description |
|---|---|
| accelerator-home-ui/src/screens/SplashScreens/BluetoothScreen.js | Adds lifecycle-scoped listener management and pairing teardown for splash Bluetooth/RCU pairing. |
| accelerator-home-ui/src/screens/SplashScreen.js | Tracks/cleans AutoRemotePair timers and loading animation; stops Bluetooth scan on exit. |
| accelerator-home-ui/src/screens/RcInformationScreen.js | Adds pairing UI + retry/timeout logic; improves pairing lifecycle teardown. |
| accelerator-home-ui/settings.json | Version bump to 6.0.25. |
Comments suppressed due to low confidence (1)
accelerator-home-ui/src/screens/SplashScreens/BluetoothScreen.js:340
_setupPairing()can still proceed after the page becomes inactive (e.g., user navigates away whilegetPluginStatus()is in-flight). In that case it may start pairing and re-register Thunder listeners in the background, which defeats the page-level scan limitation. Add a guard inside the async callbacks to bail out when pairing has been torn down (you already resetpairingInitializedin_inactive()).
appApi.getPluginStatus('org.rdk.RemoteControl').then(result => {
if (result[0].state != "activated") {
this.LOG("SplashBluetoothScreen init RemoteControl activate.")
this.rcPairingFlow(true);
} else {
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 8 out of 8 changed files in this pull request and generated 5 comments.
Comments suppressed due to low confidence (3)
accelerator-home-ui/src/api/RemoteControl.js:56
activate()resolves early when the plugin is already activated, but still proceeds to callController.activate(). That can lead to duplicate activation attempts and double-resolve behavior (and potentially spurious activation errors/metrics). Gate the activation call on the status result and handle status-check failures explicitly.
activate() {
return new Promise((resolve, reject) => {
this.thunder.call('Controller', `status@${this.callsign}`).then(result => {
if (result[0].state === "activated") { resolve(true); return; }
});
this.INFO("RCApi: activate.");
this.thunder.Controller.activate({ callsign: this.callsign }).then(() => {
resolve(true);
}).catch(err => {
this.ERR("RCApi: Error Activation " + JSON.stringify(err));
Metrics.error(Metrics.ErrorType.OTHER,"RemoteControlApiError", "Error while Thunder Controller RemoteControl activate "+JSON.stringify(err), false, null)
reject(err)
})
})
}
accelerator-home-ui/src/api/RemoteControl.js:91
getNetStatus()always callsreject(false)even after a successfulresolve(result)because there is noreturn/else. This makes successful calls appear as failures to callers and can break pairing flows that rely ongetNetStatus().
this.thunder.call(this.callsign, 'getNetStatus').then(result => {
this.INFO("RCApi: getNetStatus result: " + JSON.stringify(result))
if (result.success) resolve(result);
reject(false);
}).catch(err => {
accelerator-home-ui/src/screens/RcInformationScreen.js:381
_active()awaitsgetNetStatus()before registeringonStatus. If the screen becomes inactive before the promise resolves, the.then(...)block can still run and attach a Thunder listener after teardown, causing background updates/leaks. Add an_isActiveguard (set true in_active, false in_inactive) before registering listeners or updating UI.
await RCApi.get().activate().catch(err => { this.ERR("RCInformationScreen error: " + JSON.stringify(err)) });
await RCApi.get().getNetStatus().then(result => {
this.INFO("RCInformationScreen getNetStatus: " + JSON.stringify(result))
onStatusCBhandle = _thunder.on('org.rdk.RemoteControl', 'onStatus', data => { this.onStatusCB(data) });
this.onStatusCB(result);
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.
Comments suppressed due to low confidence (1)
accelerator-home-ui/src/screens/RcInformationScreen.js:381
_active()awaitsgetNetStatus()and only then registers the ThunderonStatuslistener. If the screen becomes inactive beforegetNetStatus()resolves, the.then()block can still run and attach a new listener after teardown, leading to background updates/leaked listeners. Guard the async continuation with an "isActive" flag (set true in_active, false at the start of_inactive) before registering the listener / callingonStatusCB().
await RCApi.get().activate().catch(err => { this.ERR("RCInformationScreen error: " + JSON.stringify(err)) });
await RCApi.get().getNetStatus().then(result => {
this.INFO("RCInformationScreen getNetStatus: " + JSON.stringify(result))
onStatusCBhandle = _thunder.on('org.rdk.RemoteControl', 'onStatus', data => { this.onStatusCB(data) });
this.onStatusCB(result);
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
accelerator-home-ui/src/screens/SplashScreens/BluetoothScreen.js:387
_setupPairing()setspairingInitialized = trueand then starts the Bluetooth fallback path, but the fallback chain (getPluginStatusParams/btactivate) has no.catch(). If any of those promises reject, pairing can silently stall whilepairingInitializedremains true (preventing subsequent retries). Add error handling for the fallback path and resetpairingInitialized(and related state) so the screen can retry pairing rather than getting stuck.
}).catch(err => {
this.ERR('SplashBluetoothScreen getPluginStatus org.rdk.RemoteControl error: ' + JSON.stringify(err))
appApi.getPluginStatusParams('org.rdk.Bluetooth').then(pluginresult => {
this.LOG("SplashBluetoothScreen getPluginStatusParams org.rdk.Bluetooth: " + JSON.stringify(pluginresult[1]))
if (pluginresult[1] === 'deactivated') {
| clearTimeout(this.autoPairTimeout) | ||
| this.autoPairNavigateTimeout = setTimeout(() => { | ||
| if (this.hasInternet == false) this._setState('ConnectivityScreen') | ||
| else Router.navigate('home', { path: 'settings' }) | ||
| }, 2000) |
| clearTimeout(this.autoPairTimeout) | ||
| this.autoPairNavigateTimeout = setTimeout(() => { | ||
| if (this.hasInternet == false) this._setState('ConnectivityScreen') | ||
| else Router.navigate('home', { path: 'settings' }) | ||
| }, 2000) |
| text: { | ||
| text: Language.translate("Ensure to manually reset the remote control referring to its user manual."), | ||
| fontFace: CONFIG.language.font, |
No description provided.