Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Emiting Events from HeadlessTask on Android in New Arch + Bridgeless + interop layer #46050

Closed
lovegaoshi opened this issue Aug 15, 2024 · 22 comments
Assignees
Labels
Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Platform: Android Android applications. Resolution: Fixed A PR that fixes this issue has been merged. Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules)

Comments

@lovegaoshi
Copy link

Description

Hi! this is a continuation thread of #44255 to resolve the new arch (being pushed as in RN 0.75.1) compatibility to RNTP. I finally have react native compile from source set up and tried out the patch outlined in #45100 using RN 0.75.1 with the PR patched in. While old arch still functions AFAICT, the new arch now shows this error:

BUNDLE  ./index.js 

(NOBRIDGE) LOG  Bridgeless mode is enabled
(NOBRIDGE) LOG  Running "RNTPExampleNewArch" with {"rootTag":11,"initialProps":{},"fabric":true}
(NOBRIDGE) LOG  getInitialURL null
(NOBRIDGE) ERROR  Error: Failed to call into JavaScript module method AppRegistry.startHeadlessTask(). Module has not been registered as callable. Registered callable JavaScript modules (n = 8): GlobalPerformanceLogger, RCTNativeAppEventEmitter, SamplingProfiler, RCTDeviceEventEmitter, HMRClient, RCTLog, HeapCapture, Systrace. Did you forget to call `registerCallableModule`?

many thanks in advance for looking into this!

Steps to reproduce

yarn run

React Native Version

0.75.1

Affected Platforms

Runtime - Android

Areas

TurboModule - The New Native Module System, Bridgeless - The New Initialization Flow

Output of npx react-native info

System:
  OS: Linux 6.5 Ubuntu 22.04.4 LTS 22.04.4 LTS (Jammy Jellyfish)
  CPU: (16) x64 AMD Ryzen 7 3700X 8-Core Processor
  Memory: 25.98 GB / 62.72 GB
  Shell:
    version: 5.1.16
    path: /bin/bash
Binaries:
  Node:
    version: 21.7.2
    path: ~/.nvm/versions/node/v21.7.2/bin/node
  Yarn:
    version: 1.22.22
    path: ~/.nvm/versions/node/v21.7.2/bin/yarn
  npm:
    version: 10.5.0
    path: ~/.nvm/versions/node/v21.7.2/bin/npm
  Watchman: Not Found
SDKs:
  Android SDK: Not Found
IDEs:
  Android Studio: Not Found
Languages:
  Java: Not Found
  Ruby: Not Found
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.75.1
    wanted: 0.75.1
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: Not found
  newArchEnabled: false

Stacktrace or Logs

(NOBRIDGE) LOG  Bridgeless mode is enabled
 (NOBRIDGE) LOG  Running "RNTPExampleNewArch" with {"rootTag":11,"initialProps":{},"fabric":true}
 (NOBRIDGE) LOG  getInitialURL null
 (NOBRIDGE) ERROR  Error: Failed to call into JavaScript module method AppRegistry.startHeadlessTask(). Module has not been registered as callable. Registered callable JavaScript modules (n = 8): GlobalPerformanceLogger, RCTNativeAppEventEmitter, SamplingProfiler, RCTDeviceEventEmitter, HMRClient, RCTLog, HeapCapture, Systrace. Did you forget to call `registerCallableModule`?

Reproducer

https://github.com/lovegaoshi/RNTPExampleNewArch/tree/fix

Screenshots and Videos

No response

@lovegaoshi lovegaoshi added Needs: Triage 🔍 Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules) labels Aug 15, 2024
@react-native-bot react-native-bot added the Platform: Android Android applications. label Aug 15, 2024
@cortinico
Copy link
Contributor

cc @robik is this something you could help us investigate with?

@cortinico cortinico added Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. and removed Needs: Triage 🔍 labels Aug 16, 2024
@robik
Copy link
Contributor

robik commented Aug 19, 2024

@cortinico sure thing! I will look into it

@Medkhat
Copy link

Medkhat commented Sep 1, 2024

@cortinico Hi there! This issue is not only Android related, it also breaks the connection between the Metro bundler and the native side on iOS)

@robik
Copy link
Contributor

robik commented Sep 12, 2024

Hey, @lovegaoshi I've tested your repro on React Native 0.75.3 and it seems to be working well with this fix applied doublesymmetry/react-native-track-player#2290

I did not use the exact changes from the above PR, but something similar (made all function return Unit)

@lovegaoshi
Copy link
Author

lovegaoshi commented Sep 12, 2024

thank u for the attention! @robik

I just tried w/ rn 0.75.3 and the same issue persists as described in
doublesymmetry/react-native-track-player#2290 (comment)
the app builds, UI renders, but none of the events emit after buttons pressed, and the notification control is broken. If the bridge interop layer is disabled with load(bridgelessEnabled=false), everything functions as expected. This was assumed to be because RNTP uses headlessJs to register event listeners and none of them are returned as headlessJs in newarch is broken. AFAIK headlessJs is necessary as RNTP, a music playing library needs it for background playback.

log with RN 0.75.3: (where NOBRIDGE event logs are not being registered)

 BUNDLE  ./index.js 

 (NOBRIDGE) LOG  Bridgeless mode is enabled
 (NOBRIDGE) LOG  Running "RNTPExampleNewArch" with {"rootTag":11,"initialProps":{},"fabric":true}
 (NOBRIDGE) LOG  getInitialURL null
 BUNDLE  ./index.js 

 ERROR  Error: Exception in HostFunction: Could not enqueue microtask because they are disabled in this runtime, js engine: hermes
 LOG  Failed to print error:  Exception in HostFunction: Could not enqueue microtask because they are disabled in this runtime
 LOG  Event.PlaybackActiveTrackChanged {"index": 0, "lastIndex": 8, "lastPosition": 0, "lastTrack": {"artist": "David Chavez", "artwork": {"__packager_asset": true, "height": 600, "scale": 1, "uri": "http://10.0.2.2:8081/assets/src/assets/resources/artwork.jpg?platform=android&hash=9c875f17fc8e812a3c6804b402f868df", "width": 600}, "duration": 28, "title": "Pure (Demo)", "url": {"__packager_asset": true, "scale": 1, "uri": "http://10.0.2.2:8081/assets/src/assets/resources/pure.m4a?platform=android&hash=c6a1c0468e889547981a422afa6f0860"}}, "track": {"artist": "David Chavez", "artwork": "https://rntp.dev/example/Longing.jpeg", "duration": 143, "title": "Longing", "url": "https://rntp.dev/example/Longing.mp3"}}
 LOG  Event.PlaybackState {"state": "loading"}
 LOG  Event.PlaybackState {"state": "buffering"}

my repo linked above uses the patched branch already.

with RN PR patched the same error persists in 0.75.3.

BUNDLE  ./index.js 

 (NOBRIDGE) LOG  Bridgeless mode is enabled
 (NOBRIDGE) LOG  Running "RNTPExampleNewArch" with {"rootTag":11,"initialProps":{},"fabric":true}
 (NOBRIDGE) LOG  getInitialURL null
 (NOBRIDGE) ERROR  Error: Failed to call into JavaScript module method AppRegistry.startHeadlessTask(). Module has not been registered as callable. Registered callable JavaScript modules (n = 8): GlobalPerformanceLogger, RCTNativeAppEventEmitter, SamplingProfiler, RCTDeviceEventEmitter, HMRClient, RCTLog, HeapCapture, Systrace. Did you forget to call `registerCallableModule`?

@lovegaoshi
Copy link
Author

i guess its worth noting myself and others are also dependent on headlessJs being functional using the new arch besides RNTP.

@robik
Copy link
Contributor

robik commented Sep 13, 2024

Hey, I've checked it again and yeah, I missed the events. 😅

I've set up two PRs that should fix the issue (on both React Native and RNTP):

Let me know if anything else is broken I forgot to check :) cc @lovegaoshi

facebook-github-bot pushed a commit that referenced this issue Sep 13, 2024
Summary:
AppRegistry was not treated as a Callable Module in bridgeless mode. This is breaking headless tasks on Android.

Fixes:

 - #46050

## Changelog:

[ANDROID] [FIXED] - Made AppRegistry callable from Native code in Bridgeless (fixes headless tasks)

Pull Request resolved: #46480

Test Plan: Used repro from linked issue

Reviewed By: javache

Differential Revision: D62637486

Pulled By: cortinico

fbshipit-source-id: 756527003ac6d712e76c02c188e280d15c010068
@lovegaoshi
Copy link
Author

omg tysm! at a short glance everything seems to be in order. I do see the old arch now breaks - bc the old arch's appregistry related code is being removed. Could we add that back in? I can pitch the PR but im wildly not familiar w/ how FB does it.

in addition I'm assuming the new RNTP PR now breaks RN backward compatibility due to depending on this addition of getReactHost in headlessJsTaskService? I dont know how RNTP will take it, but I will def use it in my maintained fork.

my current patches look like this

ofc I need to test this heavily in prod, but unrelated, what are the chances these changes can be included in RN 0.76? cc @cortinico

again ty for the work!! @robik

@cortinico
Copy link
Contributor

ofc I need to test this heavily in prod, but unrelated, what are the chances these changes can be included in RN 0.76? cc @cortinico

As this is a bugfix, we can include it inside 0.76.
@robik @lovegaoshi can you open a pick request here https://github.com/reactwg/react-native-releases/issues/new/choose

@robik
Copy link
Contributor

robik commented Sep 13, 2024

omg tysm! at a short glance everything seems to be in order. I do see the old arch now breaks - bc the old arch's appregistry related code is being removed. Could we add that back in? I can pitch the PR but im wildly not familiar w/ how FB does it.

It should not break it as the registerCallableModule that is now used handles both new and old arch. I will look into old arch as well.

in addition I'm assuming the new RNTP PR now breaks RN backward compatibility due to depending on this addition of getReactHost in headlessJsTaskService? I dont know how RNTP will take it, but I will def use it in my maintained fork.

my current patches look like this

Well, the PR is mostly for testing and preview, forgot to mention the part about backward compatibility. Maybe some gradle sourceSet trick can work.

again ty for the work!! @robik

If anything breaks feel free to ping me here 👍

@robik
Copy link
Contributor

robik commented Sep 13, 2024

ofc I need to test this heavily in prod, but unrelated, what are the chances these changes can be included in RN 0.76? cc @cortinico

As this is a bugfix, we can include it inside 0.76. @robik @lovegaoshi can you open a pick request here reactwg/react-native-releases/issues/new/choose

I can open the pick request. I will do it after I test what is wrong with the old arch (if anything).

@lovegaoshi
Copy link
Author

ty! @robik
if helps this is the error log with the old arch:


BUNDLE  ./index.js 

 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Bridgeless Mode: false. Registered callable JavaScript modules (n = 9): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, HMRClient.
          A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native., js engine: hermes
 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Bridgeless Mode: false. Registered callable JavaScript modules (n = 9): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, HMRClient.
          A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native., js engine: hermes

@cortinico
Copy link
Contributor

@robik @lovegaoshi can we consider this close after #46480 ?

@lovegaoshi
Copy link
Author

#46480 now breaks headlessJsTaskService in the old arch; I can make mine work by not removing the old arch related line from #46480 but @robik wrote it shouldnt break

@cortinico
Copy link
Contributor

@robik can we follow up and making it non-breaking for Old Arch?

@robik
Copy link
Contributor

robik commented Sep 26, 2024

@cortinico I'll be testing it today as it should work on both archs

@robik
Copy link
Contributor

robik commented Sep 27, 2024

I believe I tested it thoroughly and it works on both platforms. @lovegaoshi are you sure you rebuilt it from source and that the patches were not overriden? I retested it on your repo directly with patches applied.

Let me know if it worked for you or not so that I can proceed with pick request :)

@lovegaoshi
Copy link
Author

lovegaoshi commented Sep 27, 2024

@robik My repo's patch didnt delete this line from #46480 (where the else handled the old arch AppRegistry), so it works on both architecture; if you delete that line as #46480 is, the old arch breaks with this log:


BUNDLE  ./index.js 

 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Bridgeless Mode: false. Registered callable JavaScript modules (n = 9): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, HMRClient.
          A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native., js engine: hermes
 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Bridgeless Mode: false. Registered callable JavaScript modules (n = 9): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, HMRClient.

appreciate the attention as always <3

@robik
Copy link
Contributor

robik commented Sep 30, 2024

@robik My repo's patch didnt delete this line from #46480 (where the else handled the old arch AppRegistry), so it works on both architecture; if you delete that line as #46480 is, the old arch breaks with this log:


BUNDLE  ./index.js 

 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Bridgeless Mode: false. Registered callable JavaScript modules (n = 9): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, HMRClient.
          A frequent cause of the error is that the application entry file path is incorrect. This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native., js engine: hermes
 ERROR  Invariant Violation: Failed to call into JavaScript module method AppRegistry.runApplication(). Module has not been registered as callable. Bridgeless Mode: false. Registered callable JavaScript modules (n = 9): Systrace, JSTimers, HeapCapture, SamplingProfiler, RCTLog, RCTDeviceEventEmitter, RCTNativeAppEventEmitter, GlobalPerformanceLogger, HMRClient.

appreciate the attention as always <3

@lovegaoshi This is interesting. The else branch should not affect this, as the new code calls Core/registerCallableModule, which does exactly what the else branch did as you can see here https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Core/registerCallableModule.js#L31

Can you try on fresh app applying the patches manually?

@lovegaoshi
Copy link
Author

flase alarm; I must have not moved the registerAppRegistry part out from the if, my apologies:S tysm for your work!

@cortinico
Copy link
Contributor

flase alarm; I must have not moved the registerAppRegistry part out from the if, my apologies:S tysm for your work!

Closing then 👍

@cortinico cortinico added the Resolution: Fixed A PR that fixes this issue has been merged. label Sep 30, 2024
@cortinico
Copy link
Contributor

@robik Thank you very much for your priceless support!

blakef pushed a commit that referenced this issue Oct 28, 2024
Summary:
AppRegistry was not treated as a Callable Module in bridgeless mode. This is breaking headless tasks on Android.

Fixes:

 - #46050

## Changelog:

[ANDROID] [FIXED] - Made AppRegistry callable from Native code in Bridgeless (fixes headless tasks)

Pull Request resolved: #46480

Test Plan: Used repro from linked issue

Reviewed By: javache

Differential Revision: D62637486

Pulled By: cortinico

fbshipit-source-id: 756527003ac6d712e76c02c188e280d15c010068
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Platform: Android Android applications. Resolution: Fixed A PR that fixes this issue has been merged. Type: New Architecture Issues and PRs related to new architecture (Fabric/Turbo Modules)
Projects
None yet
Development

No branches or pull requests

5 participants