diff --git a/android/app/build.gradle b/android/app/build.gradle index caa528711a76..445420b17a96 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -119,6 +119,18 @@ android { // Supported language variants must be declared here to avoid from being removed during the compilation. // This also helps us to not include unnecessary language variants in the APK. resConfigs "en", "es" + + externalNativeBuild { + cmake { + arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" + } + } + } + + packagingOptions { + jniLibs { + useLegacyPackaging true + } } flavorDimensions "default" diff --git a/cspell.json b/cspell.json index 5efd4621b29e..d4d826c8f32d 100644 --- a/cspell.json +++ b/cspell.json @@ -727,6 +727,8 @@ "modules/ExpensifyNitroUtils/nitrogen/**", "modules/ExpensifyNitroUtils/android/build.gradle", "modules/ExpensifyNitroUtils/android/src/main/cpp/**", + "modules/hybrid-app/android/build.gradle", + "modules/background-task/android/build.gradle", "src/TIMEZONES.ts", "tests/unit/EmojiTest.ts", "tests/unit/FastSearchTest.ts", diff --git a/modules/ExpensifyNitroUtils/android/build.gradle b/modules/ExpensifyNitroUtils/android/build.gradle index cef4d21f1e8f..c28d8c672f09 100644 --- a/modules/ExpensifyNitroUtils/android/build.gradle +++ b/modules/ExpensifyNitroUtils/android/build.gradle @@ -47,7 +47,7 @@ android { externalNativeBuild { cmake { cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" - arguments "-DANDROID_STL=c++_shared" + arguments "-DANDROID_STL=c++_shared", "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" abiFilters (*reactNativeArchitectures()) } } diff --git a/modules/background-task/android/build.gradle b/modules/background-task/android/build.gradle index ffb17153aae3..88d301341125 100644 --- a/modules/background-task/android/build.gradle +++ b/modules/background-task/android/build.gradle @@ -45,6 +45,11 @@ android { targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + externalNativeBuild { + cmake { + arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" + } + } } buildFeatures { diff --git a/modules/hybrid-app/android/build.gradle b/modules/hybrid-app/android/build.gradle index 2baa6772f697..3556fa102fc1 100644 --- a/modules/hybrid-app/android/build.gradle +++ b/modules/hybrid-app/android/build.gradle @@ -32,6 +32,12 @@ android { minSdkVersion getExtOrIntegerDefault("minSdkVersion") targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", "true" + + externalNativeBuild { + cmake { + arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" + } + } } buildFeatures { diff --git a/package-lock.json b/package-lock.json index 12a56cb7c426..2733367af5dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,7 @@ "@react-navigation/native-stack": "7.3.14", "@react-navigation/stack": "7.3.3", "@react-ng/bounds-observer": "^0.2.1", - "@rnmapbox/maps": "10.1.33", + "@rnmapbox/maps": "10.1.39", "@shopify/flash-list": "1.8.2", "@ua/react-native-airship": "~24.4.0", "awesome-phonenumber": "^5.4.0", @@ -111,7 +111,7 @@ "react-native-nitro-sqlite": "9.1.10", "react-native-onyx": "^2.0.117", "react-native-pager-view": "6.5.3", - "react-native-pdf": "6.7.3", + "react-native-pdf": "6.7.5", "react-native-performance": "^5.1.4", "react-native-permissions": "^5.4.0", "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#07d60d78d4772d47afd7a744940fc6b6d1881806", @@ -11911,9 +11911,9 @@ } }, "node_modules/@rnmapbox/maps": { - "version": "10.1.33", - "resolved": "https://registry.npmjs.org/@rnmapbox/maps/-/maps-10.1.33.tgz", - "integrity": "sha512-+J1aJnZ6q0N3044doCb6To/Eftpsn3Eq78AYPMa/Ig9x/u1eWpmbt5WbXJCehkOltGsjvTCenn+/gZKsXMZfww==", + "version": "10.1.39", + "resolved": "https://registry.npmjs.org/@rnmapbox/maps/-/maps-10.1.39.tgz", + "integrity": "sha512-h96h/wPwmuJ6Je/qDL8KTh3QSVvlX41SNVAZpEUtPpIos/n/3eDzERvBxNd/8FGZYZVR/3FcZnv4razaNCFksg==", "license": "MIT", "dependencies": { "@turf/along": "6.5.0", @@ -33008,7 +33008,7 @@ "underscore": "^1.13.6" }, "engines": { - "node": ">=20.19.1", + "node": ">=20.19.3", "npm": ">=10.8.2" }, "peerDependencies": { @@ -33056,7 +33056,9 @@ } }, "node_modules/react-native-pdf": { - "version": "6.7.3", + "version": "6.7.5", + "resolved": "https://registry.npmjs.org/react-native-pdf/-/react-native-pdf-6.7.5.tgz", + "integrity": "sha512-d1S76p2Vwax2iG+kTnjINiUMvpjtJJvtMiYwHRbgGczT8GJjtXH49YCWOd+HfnUAU29cB+knzsKGYoZBMQM8Ow==", "license": "MIT", "dependencies": { "crypto-js": "4.2.0", diff --git a/package.json b/package.json index d6bfca3a6aab..63d22171d6b3 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ "@react-navigation/native-stack": "7.3.14", "@react-navigation/stack": "7.3.3", "@react-ng/bounds-observer": "^0.2.1", - "@rnmapbox/maps": "10.1.33", + "@rnmapbox/maps": "10.1.39", "@shopify/flash-list": "1.8.2", "@ua/react-native-airship": "~24.4.0", "awesome-phonenumber": "^5.4.0", @@ -180,7 +180,7 @@ "react-native-nitro-sqlite": "9.1.10", "react-native-onyx": "^2.0.117", "react-native-pager-view": "6.5.3", - "react-native-pdf": "6.7.3", + "react-native-pdf": "6.7.5", "react-native-performance": "^5.1.4", "react-native-permissions": "^5.4.0", "react-native-picker-select": "git+https://github.com/Expensify/react-native-picker-select.git#07d60d78d4772d47afd7a744940fc6b6d1881806", diff --git a/patches/@onfido+react-native-sdk+10.6.0.patch b/patches/@onfido+react-native-sdk+10.6.0.patch index 87f0aad1618d..4b7a1ca4741a 100644 --- a/patches/@onfido+react-native-sdk+10.6.0.patch +++ b/patches/@onfido+react-native-sdk+10.6.0.patch @@ -1176,7 +1176,7 @@ index 0000000..998f79b +@end diff --git a/node_modules/@onfido/react-native-sdk/js/NativeOnfidoModule.ts b/node_modules/@onfido/react-native-sdk/js/NativeOnfidoModule.ts new file mode 100644 -index 0000000..c48f86e +index 0000000..8ed5cd0 --- /dev/null +++ b/node_modules/@onfido/react-native-sdk/js/NativeOnfidoModule.ts @@ -0,0 +1,13 @@ @@ -1227,7 +1227,7 @@ index db35471..fa6c1ef 100644 addCustomMediaCallback(callback: (result: OnfidoMediaResult) => OnfidoMediaResult) { diff --git a/node_modules/@onfido/react-native-sdk/onfido-react-native-sdk.podspec b/node_modules/@onfido/react-native-sdk/onfido-react-native-sdk.podspec -index a9de0d0..da83d9f 100644 +index a9de0d0..ed1e6fd 100644 --- a/node_modules/@onfido/react-native-sdk/onfido-react-native-sdk.podspec +++ b/node_modules/@onfido/react-native-sdk/onfido-react-native-sdk.podspec @@ -2,6 +2,8 @@ require "json" @@ -1317,4 +1317,4 @@ index 49f9d4c..1b9f304 100755 + sed -i '' -e "s/_pluginVersion = @\"[0-9]*\.[0-9]*\.[0-9]*\"/_pluginVersion = @\"$2\"/g" $1 } - update_manifest ${MANIFEST_FILE} $PACKAGE_VERSION \ No newline at end of file + update_manifest ${MANIFEST_FILE} $PACKAGE_VERSION diff --git a/patches/@onfido/react-native-sdk/@onfido+react-native-sdk+10.6.0+002+android-enable-16kb-memory-page-size.patch b/patches/@onfido/react-native-sdk/@onfido+react-native-sdk+10.6.0+002+android-enable-16kb-memory-page-size.patch new file mode 100644 index 000000000000..2695317dc4cb --- /dev/null +++ b/patches/@onfido/react-native-sdk/@onfido+react-native-sdk+10.6.0+002+android-enable-16kb-memory-page-size.patch @@ -0,0 +1,17 @@ +diff --git a/node_modules/@onfido/react-native-sdk/android/build.gradle b/node_modules/@onfido/react-native-sdk/android/build.gradle +index 895bfd7..257605f 100644 +--- a/node_modules/@onfido/react-native-sdk/android/build.gradle ++++ b/node_modules/@onfido/react-native-sdk/android/build.gradle +@@ -93,6 +93,12 @@ android { + versionName "1.0" + multiDexEnabled true + consumerProguardFiles 'proguard-rules.pro' ++ ++ externalNativeBuild { ++ cmake { ++ arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" ++ } ++ } + } + lintOptions { + abortOnError false diff --git a/patches/@onfido/react-native-sdk/details.md b/patches/@onfido/react-native-sdk/details.md new file mode 100644 index 000000000000..a507f91afe9d --- /dev/null +++ b/patches/@onfido/react-native-sdk/details.md @@ -0,0 +1,8 @@ +# `@onfido/react-native-sdk` patches + +### [@onfido+react-native-sdk+10.6.0+002+android-enable-16kb-memory-page-size.patch](@onfido+react-native-sdk+10.6.0+002+android-enable-16kb-memory-page-size.patch) + +- Reason: Updates the packaging of the library on Android to enable 16KB memory page sizes on Android. +- Upstream PR/issue: TODO +- E/App issue: [#63871](https://github.com/Expensify/App/issues/63871) +- PR Introducing Patch: [#64640](https://github.com/Expensify/App/pull/64640) diff --git a/patches/@react-native-firebase+crashlytics+12.9.3+001+hybrid-app.patch b/patches/@react-native-firebase/crashlytics/@react-native-firebase+crashlytics+12.9.3+001+hybrid-app.patch similarity index 100% rename from patches/@react-native-firebase+crashlytics+12.9.3+001+hybrid-app.patch rename to patches/@react-native-firebase/crashlytics/@react-native-firebase+crashlytics+12.9.3+001+hybrid-app.patch diff --git a/patches/@react-native-firebase/crashlytics/@react-native-firebase+crashlytics+12.9.3+002+android-enable-16kb-memory-page-size.patch b/patches/@react-native-firebase/crashlytics/@react-native-firebase+crashlytics+12.9.3+002+android-enable-16kb-memory-page-size.patch new file mode 100644 index 000000000000..63a043308093 --- /dev/null +++ b/patches/@react-native-firebase/crashlytics/@react-native-firebase+crashlytics+12.9.3+002+android-enable-16kb-memory-page-size.patch @@ -0,0 +1,30 @@ +diff --git a/node_modules/@react-native-firebase/crashlytics/android/build.gradle b/node_modules/@react-native-firebase/crashlytics/android/build.gradle +index 9b89ae7..3069e6c 100644 +--- a/node_modules/@react-native-firebase/crashlytics/android/build.gradle ++++ b/node_modules/@react-native-firebase/crashlytics/android/build.gradle +@@ -67,6 +67,12 @@ project.ext { + android { + defaultConfig { + multiDexEnabled true ++ ++ externalNativeBuild { ++ cmake { ++ arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" ++ } ++ } + } + lintOptions { + disable 'GradleCompatible' +@@ -87,7 +93,11 @@ dependencies { + api appProject + implementation platform("com.google.firebase:firebase-bom:${ReactNative.ext.getVersion("firebase", "bom")}") + implementation "com.google.firebase:firebase-crashlytics" +- implementation "com.google.firebase:firebase-crashlytics-ndk" ++ implementation ("com.google.firebase:firebase-crashlytics-ndk") { ++ version { ++ strictly "[19.0.2,)" ++ } ++ } + } + + ReactNative.shared.applyPackageVersion() diff --git a/patches/@react-native-firebase/crashlytics/details.md b/patches/@react-native-firebase/crashlytics/details.md new file mode 100644 index 000000000000..4a93a33efca9 --- /dev/null +++ b/patches/@react-native-firebase/crashlytics/details.md @@ -0,0 +1,15 @@ +# `@react-native-firebase/crashlytics` patches + +### [@react-native-firebase+crashlytics+12.9.3+001+hybrid-app.patch](@react-native-firebase+crashlytics+12.9.3+001+hybrid-app.patch) + +- Reason: This patch is needed for support of HybridApp with React Native version >=0.75 +- Upstream PR/issue: N/A +- E/App issue: N/A +- PR Introducing Patch: [#45289](https://github.com/Expensify/App/pull/45289) + +### [@react-native-firebase+crashlytics+12.9.3+002+android-jni-packaging-for-16kb-memory-page-size.patch](@react-native-firebase+crashlytics+12.9.3+002+android-jni-packaging-for-16kb-memory-page-size.patch) + +- Reason: Updates the packaging of the library on Android to enable 16KB memory page sizes on Android. +- Upstream PR/issue: [#7954](https://github.com/invertase/react-native-firebase/issues/7954) +- E/App issue: [#63871](https://github.com/Expensify/App/issues/63871) +- PR Introducing Patch: [#64640](https://github.com/Expensify/App/pull/64640) diff --git a/patches/@rnmapbox+maps+10.1.33.patch b/patches/@rnmapbox+maps+10.1.33.patch deleted file mode 100644 index 683f92326cba..000000000000 --- a/patches/@rnmapbox+maps+10.1.33.patch +++ /dev/null @@ -1,200 +0,0 @@ -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/images/RNMBXImagesManager.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/images/RNMBXImagesManager.kt -index fb2147f..241d789 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/images/RNMBXImagesManager.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/images/RNMBXImagesManager.kt -@@ -249,10 +249,10 @@ class RNMBXImagesManager(private val mContext: ReactApplicationContext) : - Logger.e("RNMBXImages", "each element of strech should be an array but was: ${array.getDynamic(i)}") - } else { - val pair = array.getArray(i) -- if (pair.size() != 2 || pair.getType(0) != ReadableType.Number || pair.getType(1) != ReadableType.Number) { -+ if (pair?.size() != 2 || pair.getType(0) != ReadableType.Number || pair.getType(1) != ReadableType.Number) { - Logger.e("RNMBXImages", "each element of stretch should be pair of 2 integers but was ${pair}") - } -- result.add(ImageStretches(pair.getDouble(0).toFloat(), pair.getDouble(1).toFloat())) -+ result.add(ImageStretches(pair!!.getDouble(0).toFloat(), pair.getDouble(1).toFloat())) - } - } - return result; -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt -index 688f3a6..0627519 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapView.kt -@@ -15,7 +15,7 @@ import android.widget.FrameLayout - import androidx.lifecycle.Lifecycle - import androidx.lifecycle.LifecycleOwner - import androidx.lifecycle.LifecycleRegistry --import androidx.lifecycle.ViewTreeLifecycleOwner -+import androidx.lifecycle.setViewTreeLifecycleOwner - import com.facebook.react.bridge.* - import com.mapbox.android.gestures.* - import com.mapbox.bindgen.Value -@@ -131,12 +131,13 @@ class RNMBXLifeCycle { - } - } - -- override fun getLifecycle(): Lifecycle { -- return lifecycleRegistry -+ override val lifecycle: Lifecycle -+ get() = lifecycleRegistry -+ - } - } -- ViewTreeLifecycleOwner.set(view, lifecycleOwner); -- } -+ view.setViewTreeLifecycleOwner(lifecycleOwner) -+ - lifecycleOwner?.handleLifecycleEvent(Lifecycle.Event.ON_START) - } - -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt -index 220cf54..3e026c7 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/mapview/RNMBXMapViewManager.kt -@@ -34,13 +34,13 @@ import java.util.HashMap - - fun ReadableArray.forEachString(action: (String) -> Unit) { - for (i in 0 until size()) { -- action(getString(i)) -+ action(getString(i)!!) - } - } - - fun ReadableArray.asArrayString(): Array { - val result = Array(size()) { -- getString(it) -+ getString(it)!! - } - return result - } -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleValue.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleValue.kt -index db13128..99fd5c8 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleValue.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/RNMBXStyleValue.kt -@@ -82,7 +82,7 @@ class RNMBXStyleValue(config: ReadableMap) { - val result = ArrayList(arr!!.size()) - for (i in 0 until arr.size()) { - val item = arr.getMap(i) -- result.add(item.getDouble("value")) -+ result.add(item!!.getDouble("value")) - } - return result - } -@@ -104,7 +104,7 @@ class RNMBXStyleValue(config: ReadableMap) { - val result = ArrayList(arr!!.size()) - for (i in 0 until arr.size()) { - val item = arr.getMap(i) -- val value = item.getString("value") -+ val value = item!!.getString("value") - if (value != null) { - result.add(value) - } else { -@@ -121,9 +121,9 @@ class RNMBXStyleValue(config: ReadableMap) { - val result = WritableNativeMap() - for (i in 0 until keyValues!!.size()) { - val keyValue = keyValues.getArray(i) -- val stringKey = keyValue.getMap(0).getString("value") -+ val stringKey = keyValue!!.getMap(0)!!.getString("value") - val value = WritableNativeMap() -- value.merge(keyValue.getMap(1)) -+ value.merge(keyValue.getMap(1)!!) - result.putMap(stringKey!!, value) - } - return result -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceManager.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceManager.kt -index 637372d..da3bf91 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceManager.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXShapeSourceManager.kt -@@ -119,7 +119,7 @@ class RNMBXShapeSourceManager(private val mContext: ReactApplicationContext, val - ) - ReadableType.Boolean -> Expression.literal(expressions.getBoolean(iExp)) - ReadableType.Number -> Expression.literal(expressions.getDouble(iExp)) -- else -> Expression.literal(expressions.getString(iExp)) -+ else -> Expression.literal(expressions.getString(iExp)!!) - } - builder.add(argument) - } -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXTileSourceManager.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXTileSourceManager.kt -index 3b0a072..2530916 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXTileSourceManager.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/components/styles/sources/RNMBXTileSourceManager.kt -@@ -41,7 +41,7 @@ abstract class RNMBXTileSourceManager> internal construct - val urls: MutableList = ArrayList() - for (i in 0 until tileUrlTemplates.asArray().size()) { - if (tileUrlTemplates.asArray().getType(0) == ReadableType.String) { -- urls.add(tileUrlTemplates.asArray().getString(i)) -+ urls.add(tileUrlTemplates.asArray().getString(i)!!) - } - } - source!!.tileUrlTemplates = urls -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/shapeAnimators/RNMBXChangeLineOffsetsShapeAnimatorModule.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/shapeAnimators/RNMBXChangeLineOffsetsShapeAnimatorModule.kt -index 28d1020..41f80d5 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/shapeAnimators/RNMBXChangeLineOffsetsShapeAnimatorModule.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/shapeAnimators/RNMBXChangeLineOffsetsShapeAnimatorModule.kt -@@ -210,7 +210,7 @@ private fun buildLineString(_coordinates: ReadableArray): LineString { - - for (i in 0 until _coordinates.size()) { - val arr = _coordinates.getArray(i) -- val coord = Point.fromLngLat(arr.getDouble(0), arr.getDouble(1)) -+ val coord = Point.fromLngLat(arr!!.getDouble(0), arr.getDouble(1)) - coordinates = coordinates.plus(coord) - } - -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/Dynamic.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/Dynamic.kt -index d52fa21..1a17410 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/Dynamic.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/Dynamic.kt -@@ -38,9 +38,9 @@ fun ReadableArray.toValue(): Value { - ReadableType.Null -> Value.nullValue() - ReadableType.Boolean -> Value.valueOf(getBoolean(i)) - ReadableType.Number -> Value.valueOf(getDouble(i)) -- ReadableType.String -> Value.valueOf(getString(i)) -- ReadableType.Array -> getArray(i).toValue() -- ReadableType.Map -> getMap(i).toValue() -+ ReadableType.String -> Value.valueOf(getString(i)!!) -+ ReadableType.Array -> getArray(i)!!.toValue() -+ ReadableType.Map -> getMap(i)!!.toValue() - }) - } - return Value.valueOf(result) -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableArray.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableArray.kt -index 83a78bc..b27dce1 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableArray.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableArray.kt -@@ -46,8 +46,8 @@ fun ReadableArray.toJsonArray() : JsonArray { - val result = JsonArray(size()) - for (i in 0 until size()) { - when (getType(i)) { -- ReadableType.Map -> result.add(getMap(i).toJsonObject()) -- ReadableType.Array -> result.add(getArray(i).toJsonArray()) -+ ReadableType.Map -> result.add(getMap(i)?.toJsonObject()) -+ ReadableType.Array -> result.add(getArray(i)?.toJsonArray()) - ReadableType.Null -> result.add(null as JsonElement?) - ReadableType.Number -> result.add(getDouble(i)) - ReadableType.String -> result.add(getString(i)) -diff --git a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableMap.kt b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableMap.kt -index c69ef8c..912601f 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableMap.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/java/com/rnmapbox/rnmbx/utils/extensions/ReadableMap.kt -@@ -25,7 +25,7 @@ fun ReadableMap.forEach(action: (String, Any) -> Unit) { - val iterator = this.entryIterator - while (iterator.hasNext()) { - val next = iterator.next() -- action(next.key, next.value) -+ action(next.key, next.value!!) - } - } - fun ReadableMap.getIfDouble(key: String): Double? { -diff --git a/node_modules/@rnmapbox/maps/android/src/main/rn-compat/rn75/com/rnmapbox/rnmbx/rncompat/ReadableMap.kt b/node_modules/@rnmapbox/maps/android/src/main/rn-compat/rn75/com/rnmapbox/rnmbx/rncompat/ReadableMap.kt -index fee7f22..194e630 100644 ---- a/node_modules/@rnmapbox/maps/android/src/main/rn-compat/rn75/com/rnmapbox/rnmbx/rncompat/ReadableMap.kt -+++ b/node_modules/@rnmapbox/maps/android/src/main/rn-compat/rn75/com/rnmapbox/rnmbx/rncompat/ReadableMap.kt -@@ -1,7 +1,7 @@ - package com.rnmapbox.rnmbx.rncompat.readable_map - import com.facebook.react.bridge.ReadableMap - --fun ReadableMap.getEntryIterator(): Iterator> -+fun ReadableMap.getEntryIterator(): Iterator> - { - return this.entryIterator - } -\ No newline at end of file diff --git a/patches/@rnmapbox/maps/@rnmapbox+maps+10.1.39+001+android-enable-16kb-memory-page-size.patch b/patches/@rnmapbox/maps/@rnmapbox+maps+10.1.39+001+android-enable-16kb-memory-page-size.patch new file mode 100644 index 000000000000..7341f3a128d7 --- /dev/null +++ b/patches/@rnmapbox/maps/@rnmapbox+maps+10.1.39+001+android-enable-16kb-memory-page-size.patch @@ -0,0 +1,17 @@ +diff --git a/node_modules/@rnmapbox/maps/android/build.gradle b/node_modules/@rnmapbox/maps/android/build.gradle +index 09cee53..40ee8c7 100644 +--- a/node_modules/@rnmapbox/maps/android/build.gradle ++++ b/node_modules/@rnmapbox/maps/android/build.gradle +@@ -123,6 +123,12 @@ android { + versionCode 1 + versionName "1.0" + buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() ++ ++ externalNativeBuild { ++ cmake { ++ arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" ++ } ++ } + } + + compileOptions { \ No newline at end of file diff --git a/patches/@rnmapbox/maps/details.md b/patches/@rnmapbox/maps/details.md new file mode 100644 index 000000000000..0a1798db712a --- /dev/null +++ b/patches/@rnmapbox/maps/details.md @@ -0,0 +1,8 @@ +# `@rnmapbox/maps` patches + +### [@rnmapbox+maps+10.1.39+001+android-jni-packaging-for-16kb-memory-page-size.patch](@rnmapbox+maps+10.1.39+001+android-jni-packaging-for-16kb-memory-page-size.patch) + +- Reason: Updates the packaging of the library on Android to enable 16KB memory page sizes on Android. +- Upstream PR/issue: TODO +- E/App issue: [#63871](https://github.com/Expensify/App/issues/63871) +- PR Introducing Patch: [#64640](https://github.com/Expensify/App/pull/64640) diff --git a/patches/expo-av+15.1.5+003+android-enable-16kb-memory-page-size.patch b/patches/expo-av+15.1.5+003+android-enable-16kb-memory-page-size.patch new file mode 100644 index 000000000000..147bae0c33b4 --- /dev/null +++ b/patches/expo-av+15.1.5+003+android-enable-16kb-memory-page-size.patch @@ -0,0 +1,25 @@ +diff --git a/node_modules/expo-av/android/build.gradle b/node_modules/expo-av/android/build.gradle +index 3ecd645..dcdc27c 100644 +--- a/node_modules/expo-av/android/build.gradle ++++ b/node_modules/expo-av/android/build.gradle +@@ -37,7 +37,8 @@ android { + cppFlags "-O2 -frtti -fexceptions -Wall -fstack-protector-all" + abiFilters (*reactNativeArchitectures()) + arguments "-DANDROID_STL=c++_shared", +- "-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}" ++ "-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}", ++ "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" + } + } + } +@@ -66,6 +67,10 @@ android { + "**/libhermes.so", + "**/libjsi.so", + ] ++ ++ jniLibs { ++ useLegacyPackaging true ++ } + } + + \ No newline at end of file diff --git a/patches/expo-modules-core+2.3.12+002+android-enable-16kb-memory-page-size.patch b/patches/expo-modules-core+2.3.12+002+android-enable-16kb-memory-page-size.patch new file mode 100644 index 000000000000..b0f74af097a7 --- /dev/null +++ b/patches/expo-modules-core+2.3.12+002+android-enable-16kb-memory-page-size.patch @@ -0,0 +1,25 @@ +diff --git a/node_modules/expo-modules-core/android/build.gradle b/node_modules/expo-modules-core/android/build.gradle +index 9914a74..3f9404f 100644 +--- a/node_modules/expo-modules-core/android/build.gradle ++++ b/node_modules/expo-modules-core/android/build.gradle +@@ -89,7 +89,8 @@ android { + "-DREACT_NATIVE_TARGET_VERSION=${expoModuleExtension.reactNativeVersion.minor}", + "-DUSE_HERMES=${USE_HERMES}", + "-DIS_NEW_ARCHITECTURE_ENABLED=${isNewArchitectureEnabled}", +- "-DUNIT_TEST=${isExpoModulesCoreTests}" ++ "-DUNIT_TEST=${isExpoModulesCoreTests}", ++ "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" + } + } + } +@@ -134,6 +135,10 @@ android { + "**/libyoga.so", + ] + ++ jniLibs { ++ useLegacyPackaging true ++ } ++ + // Required or mockk will crash + resources { + excludes += [ \ No newline at end of file diff --git a/patches/react-native-fs+2.20.0+001+android-jni-packaging-for-16kb-memory-page-size.patch b/patches/react-native-fs+2.20.0+001+android-jni-packaging-for-16kb-memory-page-size.patch new file mode 100644 index 000000000000..ca62b32b4b33 --- /dev/null +++ b/patches/react-native-fs+2.20.0+001+android-jni-packaging-for-16kb-memory-page-size.patch @@ -0,0 +1,27 @@ +diff --git a/node_modules/react-native-fs/android/build.gradle b/node_modules/react-native-fs/android/build.gradle +index ddef857..7fa789c 100644 +--- a/node_modules/react-native-fs/android/build.gradle ++++ b/node_modules/react-native-fs/android/build.gradle +@@ -23,10 +23,22 @@ android { + targetSdkVersion safeExtGet('targetSdkVersion', 26) + versionCode 1 + versionName "1.0" ++ ++ externalNativeBuild { ++ cmake { ++ arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" ++ } ++ } + } + lintOptions { + abortOnError false + } ++ ++ packagingOptions { ++ jniLibs { ++ useLegacyPackaging true ++ } ++ } + } + + dependencies { \ No newline at end of file diff --git a/patches/react-native-pdf/details.md b/patches/react-native-pdf/details.md deleted file mode 100644 index 5a5ed1474de4..000000000000 --- a/patches/react-native-pdf/details.md +++ /dev/null @@ -1,14 +0,0 @@ -# `react-native-pdf` patches - -### [react-native-pdf+6.7.3+001+update-podspec-to-support-new-arch.patch](react-native-pdf+6.7.3+001+update-podspec-to-support-new-arch.patch) - -- Reason: - - ``` - This patch updates the react-native-pdf.podspec to ensure compatibility with React Native's New Architecture on iOS by replacing manual dependency declarations - with Meta's recommended `install_modules_dependencies` function - ``` - -- Upstream PR/issue: https://github.com/wonday/react-native-pdf/pull/803 -- E/App issue: 🛑 -- PR Introducing Patch: https://github.com/Expensify/App/pull/13767 diff --git a/patches/react-native-pdf/react-native-pdf+6.7.3+001+update-podspec-to-support-new-arch.patch b/patches/react-native-pdf/react-native-pdf+6.7.3+001+update-podspec-to-support-new-arch.patch deleted file mode 100644 index 5e81ac17360b..000000000000 --- a/patches/react-native-pdf/react-native-pdf+6.7.3+001+update-podspec-to-support-new-arch.patch +++ /dev/null @@ -1,30 +0,0 @@ -diff --git a/node_modules/react-native-pdf/react-native-pdf.podspec b/node_modules/react-native-pdf/react-native-pdf.podspec -index fb36140..5d5f19e 100644 ---- a/node_modules/react-native-pdf/react-native-pdf.podspec -+++ b/node_modules/react-native-pdf/react-native-pdf.podspec -@@ -17,24 +17,11 @@ Pod::Spec.new do |s| - s.framework = "PDFKit" - - if fabric_enabled -- folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' -- -- s.pod_target_xcconfig = { -- 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/RCT-Folly"', -- "CLANG_CXX_LANGUAGE_STANDARD" => "c++17", -- } - s.platforms = { ios: '11.0', tvos: '11.0' } -- s.compiler_flags = folly_compiler_flags + ' -DRCT_NEW_ARCH_ENABLED' - s.source_files = 'ios/**/*.{h,m,mm,cpp}' - s.requires_arc = true - -- s.dependency "React" -- s.dependency "React-RCTFabric" -- s.dependency "React-Codegen" -- s.dependency "RCT-Folly" -- s.dependency "RCTRequired" -- s.dependency "RCTTypeSafety" -- s.dependency "ReactCommon/turbomodule/core" -+ install_modules_dependencies(s) - else - s.platform = :ios, '8.0' - s.source_files = 'ios/**/*.{h,m,mm}' diff --git a/patches/react-native-safe-area-context/details.md b/patches/react-native-safe-area-context/details.md new file mode 100644 index 000000000000..b939cd2f31e5 --- /dev/null +++ b/patches/react-native-safe-area-context/details.md @@ -0,0 +1,8 @@ +# `react-native-safe-area-context` patches + +### [react-native-safe-area-context+5.4.0+001+android-jni-packaging-for-16kb-memory-page-size.patch](react-native-safe-area-context+5.4.0+001+android-jni-packaging-for-16kb-memory-page-size.patch) + +- Reason: Updates the packaging of the library on Android to enable 16KB memory page sizes on Android. +- Upstream PR/issue: TODO +- E/App issue: [#63871](https://github.com/Expensify/App/issues/63871) +- PR Introducing Patch: [#64640](https://github.com/Expensify/App/pull/64640) diff --git a/patches/react-native-safe-area-context/react-native-safe-area-context+5.4.0+001+android-enable-16kb-memory-page-size.patch b/patches/react-native-safe-area-context/react-native-safe-area-context+5.4.0+001+android-enable-16kb-memory-page-size.patch new file mode 100644 index 000000000000..a472e3ca51b0 --- /dev/null +++ b/patches/react-native-safe-area-context/react-native-safe-area-context+5.4.0+001+android-enable-16kb-memory-page-size.patch @@ -0,0 +1,17 @@ +diff --git a/node_modules/react-native-safe-area-context/android/build.gradle b/node_modules/react-native-safe-area-context/android/build.gradle +index f324b9a..4aca83e 100644 +--- a/node_modules/react-native-safe-area-context/android/build.gradle ++++ b/node_modules/react-native-safe-area-context/android/build.gradle +@@ -68,6 +68,12 @@ android { + ndk { + abiFilters (*reactNativeArchitectures()) + } ++ ++ externalNativeBuild { ++ cmake { ++ arguments "-DANDROID_SUPPORT_FLEXIBLE_PAGE_SIZES=ON" ++ } ++ } + } + + lintOptions{ \ No newline at end of file diff --git a/scripts/check-android-16kb-memory-page-size-compatibility.sh b/scripts/check-android-16kb-memory-page-size-compatibility.sh new file mode 100755 index 000000000000..5c1f723a97ef --- /dev/null +++ b/scripts/check-android-16kb-memory-page-size-compatibility.sh @@ -0,0 +1,113 @@ +#!/bin/bash +progname="${0##*/}" +progname="${progname%.sh}" + +# usage: check_elf_alignment.sh [path to *.so files|path to *.apk] + +cleanup_trap() { + if [ -n "${tmp}" -a -d "${tmp}" ]; then + rm -rf ${tmp} + fi + exit $1 +} + +usage() { + echo "Host side script to check the ELF alignment of shared libraries." + echo "Shared libraries are reported ALIGNED when their ELF regions are" + echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED." + echo + echo "Usage: ${progname} [input-path|input-APK|input-APEX]" +} + +if [ ${#} -ne 1 ]; then + usage + exit +fi + +case ${1} in + --help | -h | -\?) + usage + exit + ;; + + *) + dir="${1}" + ;; +esac + +if ! [ -f "${dir}" -o -d "${dir}" ]; then + echo "Invalid file: ${dir}" >&2 + exit 1 +fi + +if [[ "${dir}" == *.apk ]]; then + trap 'cleanup_trap' EXIT + + echo + echo "Recursively analyzing $dir" + echo + + if { zipalign --help 2>&1 | grep -q "\-P "; }; then + echo "=== APK zip-alignment ===" + zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification' + echo "=========================" + else + echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher." + echo " You can install the latest build-tools by running the below command" + echo " and updating your \$PATH:" + echo + echo " sdkmanager \"build-tools;35.0.0-rc3\"" + fi + + dir_filename=$(basename "${dir}") + tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX") + unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1 + dir="${tmp}" +fi + +if [[ "${dir}" == *.apex ]]; then + trap 'cleanup_trap' EXIT + + echo + echo "Recursively analyzing $dir" + echo + + dir_filename=$(basename "${dir}") + tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX") + deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; } + dir="${tmp}" +fi + +RED="\e[31m" +GREEN="\e[32m" +ENDCOLOR="\e[0m" + +unaligned_libs=() + +echo +echo "=== ELF alignment ===" + +matches="$(find "${dir}" -type f)" +IFS=$'\n' +for match in $matches; do + # We could recursively call this script or rewrite it to though. + [[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}" + [[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}" + + [[ $(file "${match}") == *"ELF"* ]] || continue + + res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)" + if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then + echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)" + else + echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)" + unaligned_libs+=("${match}") + fi +done + +if [ ${#unaligned_libs[@]} -gt 0 ]; then + echo -e "${RED}Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}" +elif [ -n "${dir_filename}" ]; then + echo -e "ELF Verification Successful" +fi +echo "====================="