blob: ce37e8c81a8e7f82fdb5488e4a0f3c21a85d435f [file] [log] [blame]
// 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.
#include <memory>
#include "flutter/shell/platform/android/external_view_embedder/surface_pool.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/shell/platform/android/jni/jni_mock.h"
#include "flutter/shell/platform/android/surface/android_surface_mock.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
namespace flutter {
namespace testing {
using ::testing::ByMove;
using ::testing::Return;
class TestAndroidSurfaceFactory : public AndroidSurfaceFactory {
public:
using TestSurfaceProducer =
std::function<std::unique_ptr<AndroidSurface>(void)>;
explicit TestAndroidSurfaceFactory(TestSurfaceProducer&& surface_producer) {
surface_producer_ = surface_producer;
}
~TestAndroidSurfaceFactory() override = default;
std::unique_ptr<AndroidSurface> CreateSurface() override {
return surface_producer_();
}
private:
TestSurfaceProducer surface_producer_;
};
TEST(SurfacePool, GetLayer__AllocateOneLayer) {
auto pool = std::make_unique<SurfacePool>();
auto gr_context = GrDirectContext::MakeMock(nullptr);
auto android_context =
std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
auto jni_mock = std::make_shared<JNIMock>();
auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
.WillOnce(Return(
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))));
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()));
EXPECT_CALL(*android_surface_mock, SetNativeWindow(window));
EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
return android_surface_mock;
});
auto layer = pool->GetLayer(gr_context.get(), *android_context, jni_mock,
surface_factory);
ASSERT_NE(nullptr, layer);
ASSERT_EQ(reinterpret_cast<intptr_t>(gr_context.get()),
layer->gr_context_key);
}
TEST(SurfacePool, GetUnusedLayers) {
auto pool = std::make_unique<SurfacePool>();
auto gr_context = GrDirectContext::MakeMock(nullptr);
auto android_context =
std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
auto jni_mock = std::make_shared<JNIMock>();
auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
.WillOnce(Return(
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))));
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()));
EXPECT_CALL(*android_surface_mock, SetNativeWindow(window));
EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
return android_surface_mock;
});
auto layer = pool->GetLayer(gr_context.get(), *android_context, jni_mock,
surface_factory);
ASSERT_EQ(0UL, pool->GetUnusedLayers().size());
pool->RecycleLayers();
ASSERT_EQ(1UL, pool->GetUnusedLayers().size());
ASSERT_EQ(layer, pool->GetUnusedLayers()[0]);
}
TEST(SurfacePool, GetLayer__Recycle) {
auto pool = std::make_unique<SurfacePool>();
auto gr_context_1 = GrDirectContext::MakeMock(nullptr);
auto jni_mock = std::make_shared<JNIMock>();
auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
.WillOnce(Return(
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))));
auto android_context =
std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
auto gr_context_2 = GrDirectContext::MakeMock(nullptr);
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context_1, gr_context_2, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
// Allocate two GPU surfaces for each gr context.
EXPECT_CALL(*android_surface_mock,
CreateGPUSurface(gr_context_1.get()));
EXPECT_CALL(*android_surface_mock,
CreateGPUSurface(gr_context_2.get()));
// Set the native window once.
EXPECT_CALL(*android_surface_mock, SetNativeWindow(window));
EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
return android_surface_mock;
});
auto layer_1 = pool->GetLayer(gr_context_1.get(), *android_context, jni_mock,
surface_factory);
pool->RecycleLayers();
auto layer_2 = pool->GetLayer(gr_context_2.get(), *android_context, jni_mock,
surface_factory);
ASSERT_NE(nullptr, layer_1);
ASSERT_EQ(layer_1, layer_2);
ASSERT_EQ(reinterpret_cast<intptr_t>(gr_context_2.get()),
layer_1->gr_context_key);
ASSERT_EQ(reinterpret_cast<intptr_t>(gr_context_2.get()),
layer_2->gr_context_key);
}
TEST(SurfacePool, GetLayer__AllocateTwoLayers) {
auto pool = std::make_unique<SurfacePool>();
auto gr_context = GrDirectContext::MakeMock(nullptr);
auto android_context =
std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
auto jni_mock = std::make_shared<JNIMock>();
auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
.Times(2)
.WillOnce(Return(
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))))
.WillOnce(Return(
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
1, window))));
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()));
EXPECT_CALL(*android_surface_mock, SetNativeWindow(window));
EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
return android_surface_mock;
});
auto layer_1 = pool->GetLayer(gr_context.get(), *android_context, jni_mock,
surface_factory);
auto layer_2 = pool->GetLayer(gr_context.get(), *android_context, jni_mock,
surface_factory);
ASSERT_NE(nullptr, layer_1);
ASSERT_NE(nullptr, layer_2);
ASSERT_NE(layer_1, layer_2);
ASSERT_EQ(0, layer_1->id);
ASSERT_EQ(1, layer_2->id);
}
TEST(SurfacePool, DestroyLayers) {
auto pool = std::make_unique<SurfacePool>();
auto jni_mock = std::make_shared<JNIMock>();
EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces()).Times(0);
pool->DestroyLayers(jni_mock);
auto gr_context = GrDirectContext::MakeMock(nullptr);
auto android_context =
std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
.Times(1)
.WillOnce(Return(
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))));
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()));
EXPECT_CALL(*android_surface_mock, SetNativeWindow(window));
EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
return android_surface_mock;
});
pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory);
EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces());
pool->DestroyLayers(jni_mock);
pool->RecycleLayers();
ASSERT_TRUE(pool->GetUnusedLayers().empty());
}
TEST(SurfacePool, DestroyLayers__frameSizeChanged) {
auto pool = std::make_unique<SurfacePool>();
auto jni_mock = std::make_shared<JNIMock>();
auto gr_context = GrDirectContext::MakeMock(nullptr);
auto android_context =
std::make_shared<AndroidContext>(AndroidRenderingAPI::kSoftware);
auto window = fml::MakeRefCounted<AndroidNativeWindow>(nullptr);
auto surface_factory = std::make_shared<TestAndroidSurfaceFactory>(
[&android_context, gr_context, window]() {
auto android_surface_mock =
std::make_unique<AndroidSurfaceMock>(android_context);
EXPECT_CALL(*android_surface_mock, CreateGPUSurface(gr_context.get()));
EXPECT_CALL(*android_surface_mock, SetNativeWindow(window));
EXPECT_CALL(*android_surface_mock, IsValid()).WillOnce(Return(true));
return android_surface_mock;
});
pool->SetFrameSize(SkISize::Make(10, 10));
EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces()).Times(0);
EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
.Times(1)
.WillOnce(Return(
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
0, window))));
pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory);
pool->SetFrameSize(SkISize::Make(20, 20));
EXPECT_CALL(*jni_mock, FlutterViewDestroyOverlaySurfaces()).Times(1);
EXPECT_CALL(*jni_mock, FlutterViewCreateOverlaySurface())
.Times(1)
.WillOnce(Return(
ByMove(std::make_unique<PlatformViewAndroidJNI::OverlayMetadata>(
1, window))));
pool->GetLayer(gr_context.get(), *android_context, jni_mock, surface_factory);
ASSERT_TRUE(pool->GetUnusedLayers().empty());
}
} // namespace testing
} // namespace flutter