Skip to content

Commit

Permalink
Add feature flag to enable vector drawable support (#45394)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #45394

Changelog: [Internal]

The current `Image` implementation does not support loading [vector drawables](https://developer.android.com/develop/ui/views/graphics/vector-drawable-resources) on Android, and support has been requested many times ([issue](#16651), [issue](#27502)). I am proposing to put support behind this feature flag in order to validate against performance regressions. Adding support will require reading files from disk to determine if the resource is actually an XML file.

Reviewed By: cortinico

Differential Revision: D59647903

fbshipit-source-id: 2445d71b6769266abe4c2dda521cc2be89bf4064
  • Loading branch information
Abbondanzo authored and facebook-github-bot committed Jul 12, 2024
1 parent ab485c6 commit bac5f1f
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<9f31fa21b0dd908ec53d1586c0bd271d>>
* @generated SignedSource<<f347d3eae685a0888e834ec8ffffa20e>>
*/

/**
Expand Down Expand Up @@ -148,6 +148,12 @@ public object ReactNativeFeatureFlags {
@JvmStatic
public fun lazyAnimationCallbacks(): Boolean = accessor.lazyAnimationCallbacks()

/**
* Adds support for loading vector drawable assets in the Image component (only on Android)
*/
@JvmStatic
public fun loadVectorDrawablesOnImages(): Boolean = accessor.loadVectorDrawablesOnImages()

/**
* Propagate layout direction to Android views.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<718c08632274058c4ece4c15ed06fbfe>>
* @generated SignedSource<<03b78dd68d80c74a7be56aef64daf1e1>>
*/

/**
Expand Down Expand Up @@ -40,6 +40,7 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
private var fuseboxEnabledReleaseCache: Boolean? = null
private var initEagerTurboModulesOnNativeModulesQueueAndroidCache: Boolean? = null
private var lazyAnimationCallbacksCache: Boolean? = null
private var loadVectorDrawablesOnImagesCache: Boolean? = null
private var setAndroidLayoutDirectionCache: Boolean? = null
private var useImmediateExecutorInAndroidBridgelessCache: Boolean? = null
private var useModernRuntimeSchedulerCache: Boolean? = null
Expand Down Expand Up @@ -229,6 +230,15 @@ public class ReactNativeFeatureFlagsCxxAccessor : ReactNativeFeatureFlagsAccesso
return cached
}

override fun loadVectorDrawablesOnImages(): Boolean {
var cached = loadVectorDrawablesOnImagesCache
if (cached == null) {
cached = ReactNativeFeatureFlagsCxxInterop.loadVectorDrawablesOnImages()
loadVectorDrawablesOnImagesCache = cached
}
return cached
}

override fun setAndroidLayoutDirection(): Boolean {
var cached = setAndroidLayoutDirectionCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<9af9576364f2ec8e978604eaa1c15ee8>>
* @generated SignedSource<<b5222bfeef575fb3061ad4be8e4a1a1a>>
*/

/**
Expand Down Expand Up @@ -68,6 +68,8 @@ public object ReactNativeFeatureFlagsCxxInterop {

@DoNotStrip @JvmStatic public external fun lazyAnimationCallbacks(): Boolean

@DoNotStrip @JvmStatic public external fun loadVectorDrawablesOnImages(): Boolean

@DoNotStrip @JvmStatic public external fun setAndroidLayoutDirection(): Boolean

@DoNotStrip @JvmStatic public external fun useImmediateExecutorInAndroidBridgeless(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<ea19295997ce3b9bdebcc37989d53096>>
* @generated SignedSource<<3e0a7901e165b338871f60c22f1615a9>>
*/

/**
Expand Down Expand Up @@ -63,6 +63,8 @@ public open class ReactNativeFeatureFlagsDefaults : ReactNativeFeatureFlagsProvi

override fun lazyAnimationCallbacks(): Boolean = false

override fun loadVectorDrawablesOnImages(): Boolean = false

override fun setAndroidLayoutDirection(): Boolean = true

override fun useImmediateExecutorInAndroidBridgeless(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<63cb1200d25489b5cc9fcfa0061eccd0>>
* @generated SignedSource<<f81b71950924d0e555b9173c2a98655f>>
*/

/**
Expand Down Expand Up @@ -44,6 +44,7 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
private var fuseboxEnabledReleaseCache: Boolean? = null
private var initEagerTurboModulesOnNativeModulesQueueAndroidCache: Boolean? = null
private var lazyAnimationCallbacksCache: Boolean? = null
private var loadVectorDrawablesOnImagesCache: Boolean? = null
private var setAndroidLayoutDirectionCache: Boolean? = null
private var useImmediateExecutorInAndroidBridgelessCache: Boolean? = null
private var useModernRuntimeSchedulerCache: Boolean? = null
Expand Down Expand Up @@ -253,6 +254,16 @@ public class ReactNativeFeatureFlagsLocalAccessor : ReactNativeFeatureFlagsAcces
return cached
}

override fun loadVectorDrawablesOnImages(): Boolean {
var cached = loadVectorDrawablesOnImagesCache
if (cached == null) {
cached = currentProvider.loadVectorDrawablesOnImages()
accessedFeatureFlags.add("loadVectorDrawablesOnImages")
loadVectorDrawablesOnImagesCache = cached
}
return cached
}

override fun setAndroidLayoutDirection(): Boolean {
var cached = setAndroidLayoutDirectionCache
if (cached == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<588266c6ec144651b7fdc84b77b490e7>>
* @generated SignedSource<<77a3249e264ca893ce8f998d424cb3db>>
*/

/**
Expand Down Expand Up @@ -63,6 +63,8 @@ public interface ReactNativeFeatureFlagsProvider {

@DoNotStrip public fun lazyAnimationCallbacks(): Boolean

@DoNotStrip public fun loadVectorDrawablesOnImages(): Boolean

@DoNotStrip public fun setAndroidLayoutDirection(): Boolean

@DoNotStrip public fun useImmediateExecutorInAndroidBridgeless(): Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<9389654cf7ca12851a1af307656c807b>>
* @generated SignedSource<<61b408d16b81cca09f270c0a059166a4>>
*/

/**
Expand Down Expand Up @@ -159,6 +159,12 @@ class ReactNativeFeatureFlagsProviderHolder
return method(javaProvider_);
}

bool loadVectorDrawablesOnImages() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("loadVectorDrawablesOnImages");
return method(javaProvider_);
}

bool setAndroidLayoutDirection() override {
static const auto method =
getReactNativeFeatureFlagsProviderJavaClass()->getMethod<jboolean()>("setAndroidLayoutDirection");
Expand Down Expand Up @@ -311,6 +317,11 @@ bool JReactNativeFeatureFlagsCxxInterop::lazyAnimationCallbacks(
return ReactNativeFeatureFlags::lazyAnimationCallbacks();
}

bool JReactNativeFeatureFlagsCxxInterop::loadVectorDrawablesOnImages(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::loadVectorDrawablesOnImages();
}

bool JReactNativeFeatureFlagsCxxInterop::setAndroidLayoutDirection(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop> /*unused*/) {
return ReactNativeFeatureFlags::setAndroidLayoutDirection();
Expand Down Expand Up @@ -428,6 +439,9 @@ void JReactNativeFeatureFlagsCxxInterop::registerNatives() {
makeNativeMethod(
"lazyAnimationCallbacks",
JReactNativeFeatureFlagsCxxInterop::lazyAnimationCallbacks),
makeNativeMethod(
"loadVectorDrawablesOnImages",
JReactNativeFeatureFlagsCxxInterop::loadVectorDrawablesOnImages),
makeNativeMethod(
"setAndroidLayoutDirection",
JReactNativeFeatureFlagsCxxInterop::setAndroidLayoutDirection),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<9d36812c37a99a514fc80e83ec056365>>
* @generated SignedSource<<c5a1699b49b23c33607b58ef90a9db5b>>
*/

/**
Expand Down Expand Up @@ -90,6 +90,9 @@ class JReactNativeFeatureFlagsCxxInterop
static bool lazyAnimationCallbacks(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool loadVectorDrawablesOnImages(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

static bool setAndroidLayoutDirection(
facebook::jni::alias_ref<JReactNativeFeatureFlagsCxxInterop>);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<a26a8a821a11fcde6e71dda68b61e9f1>>
* @generated SignedSource<<19c9de459447304ed033bdef70cd2cdf>>
*/

/**
Expand Down Expand Up @@ -101,6 +101,10 @@ bool ReactNativeFeatureFlags::lazyAnimationCallbacks() {
return getAccessor().lazyAnimationCallbacks();
}

bool ReactNativeFeatureFlags::loadVectorDrawablesOnImages() {
return getAccessor().loadVectorDrawablesOnImages();
}

bool ReactNativeFeatureFlags::setAndroidLayoutDirection() {
return getAccessor().setAndroidLayoutDirection();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<b095e4240d21711ac9818a71cd9b56cb>>
* @generated SignedSource<<a03bd61ef6b064d7f46a02478b8582e3>>
*/

/**
Expand Down Expand Up @@ -137,6 +137,11 @@ class ReactNativeFeatureFlags {
*/
RN_EXPORT static bool lazyAnimationCallbacks();

/**
* Adds support for loading vector drawable assets in the Image component (only on Android)
*/
RN_EXPORT static bool loadVectorDrawablesOnImages();

/**
* Propagate layout direction to Android views.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<213b150588cbaf067c937cfa755791ca>>
* @generated SignedSource<<760396297e88583dbed0aea01ff73925>>
*/

/**
Expand Down Expand Up @@ -389,6 +389,24 @@ bool ReactNativeFeatureFlagsAccessor::lazyAnimationCallbacks() {
return flagValue.value();
}

bool ReactNativeFeatureFlagsAccessor::loadVectorDrawablesOnImages() {
auto flagValue = loadVectorDrawablesOnImages_.load();

if (!flagValue.has_value()) {
// This block is not exclusive but it is not necessary.
// If multiple threads try to initialize the feature flag, we would only
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(20, "loadVectorDrawablesOnImages");

flagValue = currentProvider_->loadVectorDrawablesOnImages();
loadVectorDrawablesOnImages_ = flagValue;
}

return flagValue.value();
}

bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() {
auto flagValue = setAndroidLayoutDirection_.load();

Expand All @@ -398,7 +416,7 @@ bool ReactNativeFeatureFlagsAccessor::setAndroidLayoutDirection() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(20, "setAndroidLayoutDirection");
markFlagAsAccessed(21, "setAndroidLayoutDirection");

flagValue = currentProvider_->setAndroidLayoutDirection();
setAndroidLayoutDirection_ = flagValue;
Expand All @@ -416,7 +434,7 @@ bool ReactNativeFeatureFlagsAccessor::useImmediateExecutorInAndroidBridgeless()
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(21, "useImmediateExecutorInAndroidBridgeless");
markFlagAsAccessed(22, "useImmediateExecutorInAndroidBridgeless");

flagValue = currentProvider_->useImmediateExecutorInAndroidBridgeless();
useImmediateExecutorInAndroidBridgeless_ = flagValue;
Expand All @@ -434,7 +452,7 @@ bool ReactNativeFeatureFlagsAccessor::useModernRuntimeScheduler() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(22, "useModernRuntimeScheduler");
markFlagAsAccessed(23, "useModernRuntimeScheduler");

flagValue = currentProvider_->useModernRuntimeScheduler();
useModernRuntimeScheduler_ = flagValue;
Expand All @@ -452,7 +470,7 @@ bool ReactNativeFeatureFlagsAccessor::useNativeViewConfigsInBridgelessMode() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(23, "useNativeViewConfigsInBridgelessMode");
markFlagAsAccessed(24, "useNativeViewConfigsInBridgelessMode");

flagValue = currentProvider_->useNativeViewConfigsInBridgelessMode();
useNativeViewConfigsInBridgelessMode_ = flagValue;
Expand All @@ -470,7 +488,7 @@ bool ReactNativeFeatureFlagsAccessor::useNewReactImageViewBackgroundDrawing() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(24, "useNewReactImageViewBackgroundDrawing");
markFlagAsAccessed(25, "useNewReactImageViewBackgroundDrawing");

flagValue = currentProvider_->useNewReactImageViewBackgroundDrawing();
useNewReactImageViewBackgroundDrawing_ = flagValue;
Expand All @@ -488,7 +506,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdate() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(25, "useRuntimeShadowNodeReferenceUpdate");
markFlagAsAccessed(26, "useRuntimeShadowNodeReferenceUpdate");

flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdate();
useRuntimeShadowNodeReferenceUpdate_ = flagValue;
Expand All @@ -506,7 +524,7 @@ bool ReactNativeFeatureFlagsAccessor::useRuntimeShadowNodeReferenceUpdateOnLayou
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(26, "useRuntimeShadowNodeReferenceUpdateOnLayout");
markFlagAsAccessed(27, "useRuntimeShadowNodeReferenceUpdateOnLayout");

flagValue = currentProvider_->useRuntimeShadowNodeReferenceUpdateOnLayout();
useRuntimeShadowNodeReferenceUpdateOnLayout_ = flagValue;
Expand All @@ -524,7 +542,7 @@ bool ReactNativeFeatureFlagsAccessor::useStateAlignmentMechanism() {
// be accessing the provider multiple times but the end state of this
// instance and the returned flag value would be the same.

markFlagAsAccessed(27, "useStateAlignmentMechanism");
markFlagAsAccessed(28, "useStateAlignmentMechanism");

flagValue = currentProvider_->useStateAlignmentMechanism();
useStateAlignmentMechanism_ = flagValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<086584dd69b004ee0f083b76d6368f84>>
* @generated SignedSource<<514f185e84b4e4253727009281717dd8>>
*/

/**
Expand Down Expand Up @@ -51,6 +51,7 @@ class ReactNativeFeatureFlagsAccessor {
bool fuseboxEnabledRelease();
bool initEagerTurboModulesOnNativeModulesQueueAndroid();
bool lazyAnimationCallbacks();
bool loadVectorDrawablesOnImages();
bool setAndroidLayoutDirection();
bool useImmediateExecutorInAndroidBridgeless();
bool useModernRuntimeScheduler();
Expand All @@ -69,7 +70,7 @@ class ReactNativeFeatureFlagsAccessor {
std::unique_ptr<ReactNativeFeatureFlagsProvider> currentProvider_;
bool wasOverridden_;

std::array<std::atomic<const char*>, 28> accessedFeatureFlags_;
std::array<std::atomic<const char*>, 29> accessedFeatureFlags_;

std::atomic<std::optional<bool>> commonTestFlag_;
std::atomic<std::optional<bool>> allowCollapsableChildren_;
Expand All @@ -91,6 +92,7 @@ class ReactNativeFeatureFlagsAccessor {
std::atomic<std::optional<bool>> fuseboxEnabledRelease_;
std::atomic<std::optional<bool>> initEagerTurboModulesOnNativeModulesQueueAndroid_;
std::atomic<std::optional<bool>> lazyAnimationCallbacks_;
std::atomic<std::optional<bool>> loadVectorDrawablesOnImages_;
std::atomic<std::optional<bool>> setAndroidLayoutDirection_;
std::atomic<std::optional<bool>> useImmediateExecutorInAndroidBridgeless_;
std::atomic<std::optional<bool>> useModernRuntimeScheduler_;
Expand Down
Loading

0 comments on commit bac5f1f

Please sign in to comment.