Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Re-lands platform brightness support on iOS #10791

Conversation

matthew-carroll
Copy link
Contributor

Re-lands platform brightness support on iOS with an #ifdef for CI.

Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't compile on ToT. Have you tried switching to the release Xcode (sudo xcode-select -s /path/to/non/beta/xcode.app) and trying a build? I think you meant #else instead of #elseif

The error:

/Users/chinmaygarde/goma/gomacc  ../../buildtools/mac-x64/clang/bin/clang++ -MMD -MF obj/flutter/shell/platform/darwin/ios/framework/Source/libFlutter.FlutterViewController.o.d -DFLUTTER_FRAMEWORK=1 -DNO_TCMALLOC -DMEMORY_TOOL_REPLACES_ALLOCATOR -DMEMORY_SANITIZER_INITIAL_SIZE -DTOOLCHAIN_VERSION=bac220c15490dcf7b7d8136f75100bbc77e8d217 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D_FORTIFY_SOURCE=2 -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCPP_ENABLE_THREAD_SAFETY_ANNOTATIONS -D_DEBUG -DSK_GL -DSK_ENABLE_DUMP_GPU -DSK_HAS_JPEG_LIBRARY -DSK_HAS_PNG_LIBRARY -DSK_HAS_WEBP_LIBRARY -DSK_HAS_WUFFS_LIBRARY -DFLUTTER_RUNTIME_MODE_DEBUG=1 -DFLUTTER_RUNTIME_MODE_PROFILE=2 -DFLUTTER_RUNTIME_MODE_RELEASE=3 -DFLUTTER_RUNTIME_MODE=1 -DU_USING_ICU_NAMESPACE=0 -DU_ENABLE_DYLOAD=0 -DU_STATIC_IMPLEMENTATION -DICU_UTIL_DATA_IMPL=ICU_UTIL_DATA_FILE -DUCHAR_TYPE=uint16_t -DSK_DISABLE_REDUCE_OPLIST_SPLITTING -DSK_LEGACY_SKCODEC_NONE_ENUM -DSK_GL -DSK_ENABLE_DUMP_GPU -DSK_DISABLE_AAA -DSK_DISABLE_READBUFFER -DSK_DISABLE_EFFECT_DESERIALIZATION -DSK_DISABLE_LEGACY_SHADERCONTEXT -DSK_DISABLE_LOWP_RASTER_PIPELINE -DSK_FORCE_RASTER_PIPELINE_BLITTER -DSK_ASSUME_GL_ES=1 -DRAPIDJSON_HAS_STDSTRING -DRAPIDJSON_HAS_CXX11_RANGE_FOR -DRAPIDJSON_HAS_CXX11_RVALUE_REFS -DRAPIDJSON_HAS_CXX11_TYPETRAITS -DRAPIDJSON_HAS_CXX11_NOEXCEPT -I../.. -Igen -I../.. -I../../flutter/third_party/txt/src -I../../third_party/harfbuzz/src -I../../third_party/icu/source/common -I../../third_party/icu/source/i18n -I../../third_party/skia -I../../third_party/rapidjson -I../../third_party/rapidjson/include -I../../third_party/dart/runtime -I../../third_party/dart/runtime/include -I../../third_party -I../../flutter/shell/platform/darwin/common/framework/Headers -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.4.sdk -miphoneos-version-min=8.0   -fno-strict-aliasing -arch arm64 -fcolor-diagnostics -Wall -Wextra -Wendif-labels -Werror -Wno-missing-field-initializers -Wno-unused-parameter -Wunguarded-availability -fvisibility=hidden -stdlib=libc++ -Wheader-hygiene -Wstring-conversion -Wthread-safety -O0 -g2  -fvisibility-inlines-hidden -fobjc-call-cxx-cdtors -std=c++17 -fno-rtti -fno-exceptions  -c ../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm -o obj/flutter/shell/platform/darwin/ios/framework/Source/libFlutter.FlutterViewController.o
../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm:973:6: error: expected value in expression
#elif
     ^
1 error generated.

@matthew-carroll
Copy link
Contributor Author

Weird that this seemed to compile for me with the wrong syntax...I'll switch to #else

- (NSString*)brightnessMode {
#if defined(__IPHONE_13_0)
if (@available(iOS 13, *)) {
UIUserInterfaceStyle style = UITraitCollection.currentTraitCollection.userInterfaceStyle;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why aren't you just using self.traitCollection here? That would avoid the SDK problem, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll give that a try

@matthew-carroll
Copy link
Contributor Author

@chinmaygarde @stuartmorgan I switched to the VC's traitCollection and removed the API check

id settingsChannel = OCMClassMock([FlutterBasicMessageChannel class]);
OCMStub([engine settingsChannel]).andReturn(settingsChannel);

FlutterViewController* vc = [[FlutterViewController alloc] initWithEngine:engine
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these tests running with ARC? Because these look like leaks. The rest of the engine does not use ARC.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No idea. I was just continuing with what I already found in this file. If you have any specific recommendations for changes, I can make them, but I'm working from a lack of iOS knowledge here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@chinmaygarde @stuartmorgan do either of you have any specific instructions for what should be done here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dnfield @gspencergoog do either of you know what changes should be made here to avoid leaks? I don't know what changes to make to bring this test code into compliance...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would turn on ARC for the test file, since that would be easy (it looks like the test project is doing it file-by-file, which seems like an odd approach; I would just enable it for the whole project).

Failing that, add an autorelease here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LongCatIsLooong helped me get ARC enabled

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to have ARC off for the project so that we can explicitly test deallocating things...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I only enabled it for this file. Do you want me to change something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, that's fine - my reply was more directed towards @stuartmorgan's comment :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well since the only test in that file is leaking the view controller, I'm pretty sure it's not deliberately off to test dealloc...

@@ -12,6 +12,6 @@ fi

set -o pipefail && xcodebuild -sdk iphonesimulator \
-scheme IosUnitTests \
-destination 'platform=iOS Simulator,name=iPhone SE,OS=12.2' \
-destination 'platform=iOS Simulator,name=iPhone 8,OS=13.0' \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This simulator variant won't be available on ToT.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reverted the OS version, but kept it on iPhone 8 because my local environment doesn't even offer an iPhone SE

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW you should be able to add iPhone SE locally, but AFAIK know of our tests depend on the simulator type at this point.

@@ -690,6 +695,11 @@ - (CGFloat)statusBarPadding {
return CGRectIsNull(intersection) ? 0.0 : intersection.size.height;
}

- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
[self onUserSettingsChanged:nil];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking more broadly at the patch rather than just the part that was failing before: why are all these layout-based methods getting onUserSettingChanged: calls? traitCollectionDidChange: makes sense, but I don't understand why a relayout would change any settings (and especially why each relayout would need to update the settings 3 times, as this change appears to be doing.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That guide says that all four of those methods are called on appearance changes, and that appearance-sensitive code should be moved into one of them. That's very different than saying that you should re-run all appearance-sensitive code in all of them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright. Do you have a recommendation? That guide does not disambiguate execution paths that lead to those methods, so it's not clear to me which subset of those methods will actually account for all use-cases where platform brightness might change. Do you know which ones we want?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation as I read it is saying that all of those are called when the appearance changes. I would implement only traitCollectionDidChange: (which best matches the conceptual use here) until/unless you have evidence that there are cases where that isn't called.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the other messages. What about when the VC is first created?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a viewDidLoad implementation and called onUserSettingsChanged:nil there to ensure we have the correct setting at the beginning.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

viewDidAppear: is already calling onUserSettingsChanged:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a risk of a timing issue there given that Flutter is running asynchronously? To me, viewDidAppear sounds like it might show the wrong brightness momentarily before Flutter updates..

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that Flutter is running asynchronously there's a risk either way; willAppear and didAppear are almost certainly in the same event loop anyway. There was a long chat thread about that originally, and I thought there was a specific plan around how to make the initial frame correct. But calling it when the engine is first created is a good start.

@matthew-carroll
Copy link
Contributor Author

matthew-carroll commented Aug 9, 2019 via email

@matthew-carroll
Copy link
Contributor Author

@chinmaygarde @stuartmorgan @dnfield @LongCatIsLooong can I merge in?

Copy link
Member

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather have a single policy for ARC in our codebase. It is extremely hard to review code when you don't know whether the missing dealloc is going to cause a leak or not because the flags the specific TU is compiled are not readily available to check.

But, I believe some of the Mac stuff already has ARC enabled TUs. So I can't fault this target for the its use of ARC either. We should figure out a migration to ARC soon though. This is getting really messy.

@@ -403,6 +403,10 @@ - (void)surfaceUpdated:(BOOL)appeared {

#pragma mark - UIViewController lifecycle notifications

- (void)viewDidLoad {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to call [super viewDidLoad] I think.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This call is unlikely to do anything where it is, because the engine is created in viewWillAppear:, which is after this. So the channel will be nil, and the message will go nowhere.

This should be right after the launchEngine: call just below (and in the initWithEngine: for that path)

@matthew-carroll
Copy link
Contributor Author

@stuartmorgan I moved the sending of user settings to the location you suggested.

FYI @darrenaustin @chinmaygarde @stuartmorgan I added the concept of platform contrast to this PR. We'll need it for Dark Mode, too, and it's essentially the same behavior that this PR added for platform brightness.

Please let me know if you think we're good to merge in with these changes.

if (@available(iOS 13, *)) {
UIAccessibilityContrast contrast = self.traitCollection.accessibilityContrast;

if (contrast == UIAccessibilityContrastHigh) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constant only exists in the iOS 13 SDK, unlike UIUserInterfaceStyleDark which is in 12. This isn't going to compile on the bots.

If you want to add this we need to go back to the early discussion of declaring the constant yourself, conditionally, behind an ifdef based on the compiling SDK, so that you can use the constant regardless of which SDK you're compiling against. Same with adding a declaration of accessibilityContrast, which is also 13+

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have an example of defining such a constant that I can reference and replicate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took a stab at only including the accessibility logic when the max API is 13 or above. Please let me know if that's sufficient.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As previously discussed, putting the actual implementation behind ifdefs doesn't do what you want, because that would mean it would only work if someone compiles their own engine locally with the Xcode beta; none of this code would actually be shipped in our library.

If this code is important to have now, then per the previous discussion what you need are declarations of the constant and the method that are behind reversed SDK ifdefs (i.e., the local declarations are used when compiling with a stable SDK, and not there to cause duplicate definition errors when using the beta SDK), allowing all of the logic here to compile regardless of SDK.

I don't have an example offhand, and would have to dig one up tomorrow. But the declarations that you need behind the ifdefs are exactly the ones that are in the beta SDK: the same name and value for the constant, and the identical signature for the method (declared via a class extension).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An example to replicate would be great. I wasn't clear on the distinction last time and I haven't been able to locate an example of it in practice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


- (void)testItReportsPlatformBrightnessWhenViewWillAppear {
// Setup test.
id engine = OCMClassMock([FlutterEngine class]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you verified that engine won't outlive this test? Per offline discussion, if a class mock outlives the test, Bad Things happen. I think the recent refactors to method channel handling means that it won't leak the engine like it used to, but I'd like to be sure.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How might I verify this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just went ahead and explicitly cleaned up every mock in each test.

@matthew-carroll matthew-carroll force-pushed the 34441_send_ios_brightness_to_flutter branch from 160e3b8 to c76d20a Compare August 15, 2019 03:08
@matthew-carroll
Copy link
Contributor Author

@stuartmorgan I pushed an update that hopefully contains the correct implementation of the conditional property inclusion that we discussed today. This appears to compile and run through tests without issue locally against 12.2 and 13. Please let me know if you think we're good to merge in with this round of changes.

Copy link
Contributor

@stuartmorgan-g stuartmorgan-g left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with style nits

UIAccessibilityContrastHigh = 2
} UIAccessibilityContrast;

@interface UITraitCollection (AccessibilityContrastApi)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I'd suggest naming the extension something like MethodsFromNewerSDK, rather than AccessibilityContrastApi, to make it very obvious that this is a declaration of something from the SDK rather than a normal extension (with an implementation).

If you do keep the current name, s/Api/API/ per ObjC naming style.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

[mockTraitCollection stopMocking];
}

- (UITraitCollection*)setupFakeTraitCollectionWithContrast:(UIAccessibilityContrast)contrast {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/setupFakeTrait.../fakeTrait.../

This isn't operating on a trait collection, it's returning one, so should be named like a getter.

Also, this should get a brief declaration comment as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@matthew-carroll matthew-carroll merged commit 5bb144c into flutter:master Aug 15, 2019
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Aug 16, 2019
engine-flutter-autoroll added a commit to flutter/flutter that referenced this pull request Aug 16, 2019
git@github.com:flutter/engine.git/compare/f8e7453f1106...4b7a552

git log f8e7453..4b7a552 --no-merges --oneline
2019-08-16 stuartmorgan@google.com Roll Dart back to e35e8833 (flutter/engine#11043)
2019-08-16 bkonyi@google.com Roll src/third_party/dart 306f8e04bb..fecc4c8f2d (4 commits)
2019-08-16 skia-flutter-autoroll@skia.org Roll src/third_party/skia 963a606677e1..6a519b8dd895 (6 commits) (flutter/engine#11042)
2019-08-15 liyuqian@google.com Hide verbose dart snapshot during run_test.py (flutter/engine#11040)
2019-08-15 chinmaygarde@google.com Remove ability to override mac_sdk_path in flutter/tools/gn (flutter/engine#11013)
2019-08-15 bkonyi@google.com Roll src/third_party/dart cd16fba718..306f8e04bb (10 commits)
2019-08-15 stuartmorgan@google.com Roll buildroot to pick up recent macOS changes (flutter/engine#11037)
2019-08-15 jason-simmons@users.noreply.github.com Remove the ParagraphImpl class from the text API (flutter/engine#11012)
2019-08-15 jason-simmons@users.noreply.github.com Disable a deprecation warning for use of a TaskDescription constructor for older platforms (flutter/engine#11029)
2019-08-15 matthew-carroll@users.noreply.github.com Re-lands platform brightness support on iOS, plus platform contrast (flutter/engine#10791)
2019-08-15 iska.kaushik@gmail.com [fuchsia] Add required trace so files for fuchsia fars (flutter/engine#11036)
2019-08-15 skia-flutter-autoroll@skia.org Roll src/third_party/skia e5dc1ebc864a..963a606677e1 (14 commits) (flutter/engine#11032)
2019-08-15 stuartmorgan@google.com Add _glfw versions of the GLFW desktop libraries (flutter/engine#11024)
2019-08-15 skia-flutter-autoroll@skia.org Roll fuchsia/sdk/core/linux-amd64 from _fvZN... to 5Nhwb... (flutter/engine#11028)
2019-08-15 bkonyi@google.com Roll src/third_party/dart 9552646dc4..cd16fba718 (5 commits)
2019-08-15 dnfield@google.com Fix first frame logic (flutter/engine#11027)
2019-08-15 dnfield@google.com remove OS version (flutter/engine#11033)
2019-08-15 skia-flutter-autoroll@skia.org Roll src/third_party/skia e30a485a68c9..e5dc1ebc864a (7 commits) (flutter/engine#11025)
2019-08-15 bkonyi@google.com Roll src/third_party/dart cae08c6813..9552646dc4 (3 commits)
2019-08-15 jason-simmons@users.noreply.github.com Remove the output directory prefix from the Android engine JAR filename (flutter/engine#11015)
2019-08-15 inthroxify@users.noreply.github.com Fix flutter/flutter #34791 (flutter/engine#9977)
2019-08-15 bkonyi@google.com Roll src/third_party/dart e35e8833ee..cae08c6813 (28 commits)
2019-08-15 skia-flutter-autoroll@skia.org Roll src/third_party/skia f3f50099533d..e30a485a68c9 (2 commits) (flutter/engine#11022)
2019-08-15 skia-flutter-autoroll@skia.org Roll src/third_party/skia 319fd3d7bcb4..f3f50099533d (4 commits) (flutter/engine#11021)

The AutoRoll server is located here: https://autoroll.skia.org/r/flutter-engine-flutter-autoroll

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff (stuartmorgan@google.com), and stop
the roller if necessary.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants