blob: aed6f2a9e059ed986f6d83a03b3885f33d99ced2 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 <fuchsia/sys/cpp/fidl.h>
#include <fuchsia/ui/app/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/fzl/vmo-mapper.h>
#include <lib/svc/cpp/services.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/sys/cpp/service_directory.h>
#include <string>
#include <src/lib/fxl/logging.h>
#include "garnet/public/lib/gtest/real_loop_fixture.h"
// Maximum number of attempts to take a screenshot and find content.
static constexpr const uint32_t kMaxAttempts = 500;
// Pixel size of the square region to attempt to observe content within.
static constexpr const uint32_t kObservationDimension = 8;
static constexpr const char* kCameraDemoUrl =
"fuchsia-pkg://fuchsia.com/camera_demo#meta/camera_demo.cmx";
class CameraDemoTest : public gtest::RealLoopFixture {
protected:
CameraDemoTest() : context_(sys::ComponentContext::Create()) {}
~CameraDemoTest() override {}
static fit::function<void(zx_status_t)> MakeErrorHandler(std::string name) {
return [name](zx_status_t status) {
FXL_PLOG(ERROR, status) << name << " disconnected";
ADD_FAILURE();
};
}
virtual void SetUp() override {
// Connect to the environment services.
context_->svc()->Connect(launcher_.NewRequest());
launcher_.set_error_handler(MakeErrorHandler("Launcher"));
context_->svc()->Connect(presenter_.NewRequest());
presenter_.set_error_handler(MakeErrorHandler("Presenter"));
context_->svc()->Connect(scenic_.NewRequest());
scenic_.set_error_handler(MakeErrorHandler("Scenic"));
// Launch the demo.
fuchsia::sys::LaunchInfo launch_info;
launch_info.url = kCameraDemoUrl;
auto service_directory =
sys::ServiceDirectory::CreateWithRequest(&launch_info.directory_request);
launcher_->CreateComponent(std::move(launch_info), controller_.NewRequest());
// Get its view provider.
fuchsia::ui::app::ViewProviderPtr view_provider;
zx_status_t status = service_directory->Connect(view_provider.NewRequest());
ASSERT_EQ(status, ZX_OK);
view_provider.set_error_handler(MakeErrorHandler("View Provider"));
// Create a view token pair.
fuchsia::ui::views::ViewHolderToken view_holder_token;
zx::eventpair view_provider_token;
status = zx::eventpair::create(0, &view_holder_token.value, &view_provider_token);
ASSERT_EQ(status, ZX_OK);
// Create a view using one token, and present it using the other.
view_provider->CreateView(std::move(view_provider_token), nullptr, nullptr);
presenter_->PresentView(std::move(view_holder_token), nullptr);
RunLoopUntilIdle();
}
virtual void TearDown() override {
if (controller_) {
controller_->Kill();
RunLoopUntilIdle();
controller_ = nullptr;
}
scenic_ = nullptr;
presenter_ = nullptr;
launcher_ = nullptr;
}
std::unique_ptr<sys::ComponentContext> context_;
fuchsia::ui::policy::PresenterPtr presenter_;
fuchsia::sys::LauncherPtr launcher_;
fuchsia::sys::ComponentControllerPtr controller_;
fuchsia::ui::scenic::ScenicPtr scenic_;
};
// Launch the demo and repeatedly take screenshots until content is observed.
TEST_F(CameraDemoTest, ContentVisible) {
bool content_found = false;
for (uint32_t attempt = 0; attempt < kMaxAttempts && !content_found; ++attempt) {
bool screenshot_returned = false;
scenic_->TakeScreenshot([&](fuchsia::ui::scenic::ScreenshotData data, bool success) {
screenshot_returned = true;
if (!success) {
// If scenic is still initializing, this will fail.
return;
}
fzl::VmoMapper mapper;
ASSERT_EQ(mapper.Map(data.data.vmo, 0, data.data.size, ZX_VM_PERM_READ), ZX_OK);
for (uint32_t r = 0; r < kObservationDimension; ++r) {
auto row_data = static_cast<char*>(mapper.start()) +
(data.info.height / 2 - kObservationDimension / 2 + r) * data.info.stride;
for (uint32_t c = 0; c < kObservationDimension; ++c) {
auto pixel_data = reinterpret_cast<uint32_t*>(
row_data)[data.info.width / 2 - kObservationDimension / 2 + c];
if (pixel_data != 0 && pixel_data != UINT32_MAX) {
content_found = true;
}
}
}
mapper.Unmap();
});
while (!HasFatalFailure() && !screenshot_returned) {
RunLoopUntilIdle();
}
}
ASSERT_TRUE(content_found) << "Failed to detect content after " << kMaxAttempts
<< " capture attempts";
}