Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions engine/src/flutter/shell/platform/android/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ android_java_sources = [
"io/flutter/Log.java",
"io/flutter/app/FlutterApplication.java",
"io/flutter/embedding/android/AndroidTouchProcessor.java",
"io/flutter/embedding/android/ContentSizingFlag.java",
"io/flutter/embedding/android/ExclusiveAppComponent.java",
"io/flutter/embedding/android/FlutterActivity.java",
"io/flutter/embedding/android/FlutterActivityAndFragmentDelegate.java",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "flutter/common/constants.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/trace_event.h"
#include "fml/make_copyable.h"

namespace flutter {

Expand Down Expand Up @@ -225,7 +226,11 @@ void AndroidExternalViewEmbedder::PrepareFlutterView(
DestroySurfaces();
}
surface_pool_->SetFrameSize(frame_size);
jni_facade_->MaybeResizeSurfaceView(frame_size.width, frame_size.height);

task_runners_.GetPlatformTaskRunner()->PostTask(
fml::MakeCopyable([jni_facade = jni_facade_, frame_size = frame_size]() {
jni_facade->MaybeResizeSurfaceView(frame_size.width, frame_size.height);
}));

frame_size_ = frame_size;
device_pixel_ratio_ = device_pixel_ratio;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,11 @@ void AndroidExternalViewEmbedder2::PrepareFlutterView(
DestroySurfaces();
}
surface_pool_->SetFrameSize(frame_size);
jni_facade_->MaybeResizeSurfaceView(frame_size.width, frame_size.height);

task_runners_.GetPlatformTaskRunner()->PostTask(
fml::MakeCopyable([jni_facade = jni_facade_, frame_size = frame_size]() {
jni_facade->MaybeResizeSurfaceView(frame_size.width, frame_size.height);
}));

frame_size_ = frame_size;
device_pixel_ratio_ = device_pixel_ratio;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,13 @@
#include "flutter/flow/embedded_views.h"
#include "flutter/flow/surface.h"
#include "flutter/fml/raster_thread_merger.h"
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/thread.h"
#include "flutter/shell/common/thread_host.h"
#include "flutter/shell/platform/android/jni/jni_mock.h"
#include "flutter/shell/platform/android/surface/android_surface.h"
#include "flutter/shell/platform/android/surface/android_surface_mock.h"
#include "flutter/testing/testing.h"

#include "gmock/gmock.h"
#include "gtest/gtest.h"
Expand Down Expand Up @@ -1068,8 +1071,18 @@ TEST(AndroidExternalViewEmbedder, Teardown) {
TEST(AndroidExternalViewEmbedder, MaybeResizeSurfaceView) {
auto jni_mock = std::make_shared<JNIMock>();
auto android_context = AndroidContext(AndroidRenderingAPI::kSoftware);
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
ThreadHost::Type::kPlatform | ThreadHost::Type::kIo |
ThreadHost::Type::kUi | ThreadHost::Type::kRaster);
TaskRunners task_runners(
"test",
thread_host.platform_thread->GetTaskRunner(), // platform
thread_host.raster_thread->GetTaskRunner(), // raster
thread_host.ui_thread->GetTaskRunner(), // ui
thread_host.io_thread->GetTaskRunner() // io
);
auto embedder = std::make_unique<AndroidExternalViewEmbedder>(
android_context, jni_mock, nullptr, GetTaskRunnersForFixture());
android_context, jni_mock, nullptr, task_runners);

fml::Thread rasterizer_thread("rasterizer");
auto raster_thread_merger =
Expand All @@ -1081,6 +1094,11 @@ TEST(AndroidExternalViewEmbedder, MaybeResizeSurfaceView) {

EXPECT_CALL(*jni_mock, MaybeResizeSurfaceView(100, 200));
embedder->PrepareFlutterView(DlISize(100, 200), 1.0);

fml::AutoResetWaitableEvent latch;
fml::TaskRunner::RunNowOrPostTask(task_runners.GetPlatformTaskRunner(),
[&latch]() { latch.Signal(); });
latch.Wait();
}

TEST(AndroidExternalViewEmbedder, TeardownDoesNotCallJNIMethod) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package io.flutter.embedding.android;

import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import io.flutter.Log;

class ContentSizingFlag {

private static final String TAG = "ContentSizingFlag";

// Default to DISABLED
private static final boolean DEFAULT = false;

private static final String ENABLE_CONTENT_SIZING =
"io.flutter.embedding.android.EnableContentSizing";

static boolean isEnabled(Context context) {
// Ensure that the context is actually the application context.
final Context appContext = context.getApplicationContext();
Bundle metaData = null;
try {
ApplicationInfo applicationInfo =
appContext
.getPackageManager()
.getApplicationInfo(appContext.getPackageName(), PackageManager.GET_META_DATA);
metaData = applicationInfo.metaData;
} catch (NameNotFoundException ex) {
Log.e(TAG, "Could not get metadata");
}
Comment on lines +34 to +36

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

For better diagnostics, it's recommended to include the exception object in the log call. This will print the stack trace and provide more context when a NameNotFoundException occurs, making it easier to debug.

Suggested change
} catch (NameNotFoundException ex) {
Log.e(TAG, "Could not get metadata");
}
} catch (NameNotFoundException e) {
Log.e(TAG, "Could not get metadata", e);
}
References
  1. As per the style guide (line 32), error messages should be useful. Including the exception in the log provides valuable context like the stack trace, which is crucial for debugging. (link)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is a good suggestion but should be made on master.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

FYI @mboetger

return metaData != null ? metaData.getBoolean(ENABLE_CONTENT_SIZING, DEFAULT) : DEFAULT;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ public class FlutterImageView extends View implements RenderSurface {
@Nullable private Bitmap currentBitmap;
@Nullable private FlutterRenderer flutterRenderer;

private boolean isContentSizingEnabled = false;

public ImageReader getImageReader() {
return imageReader;
}
Expand Down Expand Up @@ -92,11 +94,16 @@ public FlutterImageView(@NonNull Context context, @NonNull AttributeSet attrs) {

private void init() {
setAlpha(0.0f);
isContentSizingEnabled = ContentSizingFlag.isEnabled(getContext());
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
FlutterMeasureSpec.onMeasure(widthMeasureSpec, heightMeasureSpec, this::setMeasuredDimension);
if (isContentSizingEnabled) {
FlutterMeasureSpec.onMeasure(widthMeasureSpec, heightMeasureSpec, this::setMeasuredDimension);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

private static void logW(String format, Object... args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ public class FlutterSurfaceView extends SurfaceView implements RenderSurface {
private boolean isPaused = false;
@Nullable private FlutterRenderer flutterRenderer;

private boolean isContentSizingEnabled = false;

private boolean shouldNotify() {
return flutterRenderer != null && !isPaused;
}
Expand Down Expand Up @@ -116,14 +118,20 @@ private void init() {
setZOrderOnTop(true);
}

isContentSizingEnabled = ContentSizingFlag.isEnabled(getContext());

// Grab a reference to our underlying Surface and register callbacks with that Surface so we
// can monitor changes and forward those changes on to native Flutter code.
getHolder().addCallback(surfaceHolderCallbackCompat);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
FlutterMeasureSpec.onMeasure(widthMeasureSpec, heightMeasureSpec, this::setMeasuredDimension);
if (isContentSizingEnabled) {
FlutterMeasureSpec.onMeasure(widthMeasureSpec, heightMeasureSpec, this::setMeasuredDimension);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

// This is a work around for TalkBack.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public class FlutterTextureView extends TextureView implements RenderSurface {
@Nullable private FlutterRenderer flutterRenderer;
@Nullable private Surface renderSurface;

private boolean isContentSizingEnabled = false;

private boolean shouldNotify() {
return flutterRenderer != null && !isPaused;
}
Expand Down Expand Up @@ -116,11 +118,17 @@ private void init() {
// Listen for when our underlying SurfaceTexture becomes available, changes size, or
// gets destroyed, and take the appropriate actions.
setSurfaceTextureListener(surfaceTextureListener);

isContentSizingEnabled = ContentSizingFlag.isEnabled(getContext());
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
FlutterMeasureSpec.onMeasure(widthMeasureSpec, heightMeasureSpec, this::setMeasuredDimension);
if (isContentSizingEnabled) {
FlutterMeasureSpec.onMeasure(widthMeasureSpec, heightMeasureSpec, this::setMeasuredDimension);
} else {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
}

@Nullable
Expand Down Expand Up @@ -273,4 +281,4 @@ private void disconnectSurfaceFromRenderer() {
renderSurface = null;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ public class FlutterView extends FrameLayout
// Maximum size allowed for a content sized view.
@VisibleForTesting static final int CONTENT_SIZING_MAX = 2 << 12;

// Flag to enable content sizing.
@VisibleForTesting boolean isContentSizingEnabled = false;

// Internal view hierarchy references.
@Nullable private FlutterSurfaceView flutterSurfaceView;
@Nullable private FlutterTextureView flutterTextureView;
Expand Down Expand Up @@ -423,6 +426,8 @@ private void init() {
addView(flutterImageView);
}

isContentSizingEnabled = ContentSizingFlag.isEnabled(getContext());

// FlutterView needs to be focusable so that the InputMethodManager can interact with it.
setFocusable(true);
setFocusableInTouchMode(true);
Expand Down Expand Up @@ -520,15 +525,15 @@ protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
viewportMetrics.width = width;
viewportMetrics.height = height;

if (heightMode == MeasureSpec.UNSPECIFIED) {
if (isContentSizingEnabled && heightMode == MeasureSpec.UNSPECIFIED) {
Log.d(TAG, "FlutterView height is set to wrap content - updating viewport metrics to max");
viewportMetrics.minHeight = 0;
viewportMetrics.maxHeight = CONTENT_SIZING_MAX;
} else {
viewportMetrics.minHeight = viewportMetrics.height;
viewportMetrics.maxHeight = viewportMetrics.height;
}
if (widthMode == MeasureSpec.UNSPECIFIED) {
if (isContentSizingEnabled && widthMode == MeasureSpec.UNSPECIFIED) {
Log.d(TAG, "FlutterView width is set to wrap content - updating viewport metrics to max");
viewportMetrics.minWidth = 0;
viewportMetrics.maxWidth = CONTENT_SIZING_MAX;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1316,8 +1316,8 @@ public void destroyOverlaySurfaces() {
platformViewsController.destroyOverlaySurfaces();
}

// This will get called on the raster thread.
@SuppressWarnings("unused")
@UiThread
public void maybeResizeSurfaceView(int width, int height) {
for (FlutterUiResizeListener listener : flutterUiResizeListeners) {
listener.resizeEngineView(width, height);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,7 @@ public SettingsChannel.MessageBuilder answer(InvocationOnMock invocation)
public void onMeasure_whenWrapContent_sendsCorrectViewportMetrics() {
FlutterSurfaceView flutterSurfaceView = spy(new FlutterSurfaceView(ctx));
FlutterView flutterView = new FlutterView(ctx, flutterSurfaceView);
flutterView.isContentSizingEnabled = true;
FlutterEngine flutterEngine = spy(new FlutterEngine(ctx, mockFlutterLoader, mockFlutterJni));
FlutterRenderer flutterRenderer = spy(new FlutterRenderer(mockFlutterJni));
when(flutterEngine.getRenderer()).thenReturn(flutterRenderer);
Expand Down