diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index a248f67405b40..0080651086c37 100755 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -1335,6 +1335,8 @@ FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/lib/src/handle_dis FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/lib/src/handle_waiter.dart FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/lib/src/init.dart FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/lib/src/system.dart +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/lib/src/zd_channel.dart +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/lib/src/zd_handle.dart FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/lib/zircon.dart FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle.cc FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/handle.h @@ -1346,9 +1348,18 @@ FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/natives.cc FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/natives.h FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.cc FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon/sdk_ext/system.h +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/basic_types.cc +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/basic_types.h +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/channel.cc +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/channel.h FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/clock.cc FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/clock.h +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/dart_dl.cc +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/dart_dl.h +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/handle.cc +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/handle.h FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart +FILE: ../../../flutter/shell/platform/fuchsia/dart-pkg/zircon_ffi/macros.h FILE: ../../../flutter/shell/platform/fuchsia/dart/compiler.dart FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/builtin_libraries.cc FILE: ../../../flutter/shell/platform/fuchsia/dart_runner/builtin_libraries.h diff --git a/shell/platform/fuchsia/dart-pkg/zircon/lib/src/init.dart b/shell/platform/fuchsia/dart-pkg/zircon/lib/src/init.dart index 3cef041e1b327..43274a718fe20 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/lib/src/init.dart +++ b/shell/platform/fuchsia/dart-pkg/zircon/lib/src/init.dart @@ -21,6 +21,12 @@ class _Bindings { final _dylib = DynamicLibrary.open(_kZirconFFILibName); _bindings = ZirconFFIBindings(_dylib); } + + final initializer = _bindings!.zircon_dart_dl_initialize; + if (initializer(NativeApi.initializeApiDLData) != 1) { + throw UnsupportedError('Unable to initialize dart:zircon_ffi.'); + } + return _bindings; } } diff --git a/shell/platform/fuchsia/dart-pkg/zircon/lib/src/zd_channel.dart b/shell/platform/fuchsia/dart-pkg/zircon/lib/src/zd_channel.dart new file mode 100644 index 0000000000000..4551e13f3a546 --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon/lib/src/zd_channel.dart @@ -0,0 +1,56 @@ +// 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. + +part of zircon; + +@pragma('vm:entry-point') +class ZDChannel { + static ZDChannel? create([int options = 0]) { + final Pointer? channelPtr = + zirconFFIBindings?.zircon_dart_channel_create(options); + if (channelPtr == null || channelPtr.address == 0) { + throw Exception('Unable to create a channel'); + } + return ZDChannel._(ZDHandlePair._(channelPtr)); + } + + static int _write(ZDHandle channel, ByteData data, List handles) { + final Pointer handleList = + zirconFFIBindings!.zircon_dart_handle_list_create(); + handles.forEach((ZDHandle handle) { + zirconFFIBindings! + .zircon_dart_handle_list_append(handleList, handle._ptr); + }); + + final Uint8List dataAsBytes = data.buffer.asUint8List(); + final Pointer byteArray = + zirconFFIBindings!.zircon_dart_byte_array_create(dataAsBytes.length); + for (int i = 0; i < dataAsBytes.length; i++) { + zirconFFIBindings!.zircon_dart_byte_array_set_value( + byteArray, i, dataAsBytes.elementAt(i)); + } + int ret = zirconFFIBindings! + .zircon_dart_channel_write(channel._ptr, byteArray, handleList); + + zirconFFIBindings!.zircon_dart_byte_array_free(byteArray); + zirconFFIBindings!.zircon_dart_handle_list_free(handleList); + return ret; + } + + int writeLeft(ByteData data, List handles) { + return _write(handlePair.left, data, handles); + } + + int writeRight(ByteData data, List handles) { + return _write(handlePair.right, data, handles); + } + + @pragma('vm:entry-point') + ZDChannel._(this.handlePair); + + final ZDHandlePair handlePair; + + @override + String toString() => 'Channel(handlePair=$handlePair)'; +} diff --git a/shell/platform/fuchsia/dart-pkg/zircon/lib/src/zd_handle.dart b/shell/platform/fuchsia/dart-pkg/zircon/lib/src/zd_handle.dart new file mode 100644 index 0000000000000..2090d78599535 --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon/lib/src/zd_handle.dart @@ -0,0 +1,77 @@ +// 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. + +part of zircon; + +@pragma('vm:entry-point') +class ZDHandle { + @pragma('vm:entry-point') + ZDHandle._(this._ptr) { + _attachFinalizer(); + } + + void _attachFinalizer() { + // TODO (kaushikiska): fix external allocation size. + final int? ret = zirconFFIBindings?.zircon_dart_handle_attach_finalizer( + this, _ptr.cast(), 128); + if (ret != 1) { + throw Exception('Unable to attach finalizer to handle'); + } + } + + int get handle => _ptr.ref.handle; + + final Pointer _ptr; + + bool isValid() { + int? ret = zirconFFIBindings?.zircon_dart_handle_is_valid(_ptr); + return ret == 1; + } + + bool close() { + assert(isValid()); + if (isValid()) { + int? ret = zirconFFIBindings?.zircon_dart_handle_close(_ptr); + return ret == 1; + } + return false; + } + + @override + bool operator ==(Object other) { + return other is ZDHandle && other.handle == handle; + } + + @override + int get hashCode => handle.hashCode; + + @override + String toString() => 'ZDHandle(handle=$handle)'; +} + +@pragma('vm:entry-point') +class ZDHandlePair { + @pragma('vm:entry-point') + ZDHandlePair._(this._ptr) + : left = ZDHandle._(_ptr.ref.left), + right = ZDHandle._(_ptr.ref.right) { + _attachFinalizer(); + } + + void _attachFinalizer() { + // TODO (kaushikiska): fix external allocation size. + final int? ret = zirconFFIBindings + ?.zircon_dart_handle_pair_attach_finalizer(this, _ptr.cast(), 128); + if (ret != 1) { + throw Exception('Unable to attach finalizer to handle'); + } + } + + final Pointer _ptr; + final ZDHandle left; + final ZDHandle right; + + @override + String toString() => 'ZDHandlePair(left=$left, right=$right)'; +} diff --git a/shell/platform/fuchsia/dart-pkg/zircon/lib/zircon.dart b/shell/platform/fuchsia/dart-pkg/zircon/lib/zircon.dart index 7942d228b2f78..bf726e3ac94d9 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/lib/zircon.dart +++ b/shell/platform/fuchsia/dart-pkg/zircon/lib/zircon.dart @@ -4,6 +4,9 @@ library zircon; +// uncomment the next line for local testing. +// import 'package:zircon_ffi/zircon_ffi.dart'; + import 'dart:convert' show utf8; import 'dart:ffi'; import 'dart:io'; @@ -16,3 +19,5 @@ part 'src/handle_disposition.dart'; part 'src/handle_waiter.dart'; part 'src/init.dart'; part 'src/system.dart'; +part 'src/zd_channel.dart'; +part 'src/zd_handle.dart'; diff --git a/shell/platform/fuchsia/dart-pkg/zircon/pubspec.yaml b/shell/platform/fuchsia/dart-pkg/zircon/pubspec.yaml index 4fb6995fba9c9..d82a3ccf9e8b4 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/pubspec.yaml +++ b/shell/platform/fuchsia/dart-pkg/zircon/pubspec.yaml @@ -2,5 +2,19 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +name: zircon + environment: - sdk: '>=2.11.0 <3.0.0' + sdk: '>=2.12.0 <3.0.0' + + +# Uncomment block for local testing + +# dependencies: +# zircon_ffi: +# path: ../zircon_ffi + +# dev_dependencies: +# test: ^1.17.10 + +# block end diff --git a/shell/platform/fuchsia/dart-pkg/zircon/test/channel_test.dart b/shell/platform/fuchsia/dart-pkg/zircon/test/channel_test.dart index 22955cdd36e3f..3a6994b793778 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon/test/channel_test.dart +++ b/shell/platform/fuchsia/dart-pkg/zircon/test/channel_test.dart @@ -23,6 +23,14 @@ void main() { expect(pair.second.isValid, isTrue); }); + test('[ffi] create channel', () { + final ZDChannel? channel = ZDChannel.create(); + expect(channel, isNotNull); + final ZDHandlePair pair = channel!.handlePair; + expect(pair.left.isValid(), isTrue); + expect(pair.right.isValid(), isTrue); + }); + test('close channel', () { final HandlePairResult pair = System.channelCreate(); expect(pair.first.close(), equals(0)); @@ -34,6 +42,18 @@ void main() { equals(ZX.ERR_PEER_CLOSED)); }); + test('[ffi] close channel', () { + final ZDChannel? channel = ZDChannel.create(); + final ZDHandlePair pair = channel!.handlePair; + expect(pair.left.close(), isTrue); + expect(pair.left.isValid, isFalse); + expect(pair.right.isValid, isTrue); + expect(channel.writeLeft(ByteData(1), []), + equals(ZX.ERR_BAD_HANDLE)); + expect(channel.writeRight(ByteData(1), []), + equals(ZX.ERR_PEER_CLOSED)); + }); + test('channel bytes', () { final HandlePairResult pair = System.channelCreate(); diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/BUILD.gn b/shell/platform/fuchsia/dart-pkg/zircon_ffi/BUILD.gn index 13ccb8ccf4d1e..3016d4ed0eec5 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon_ffi/BUILD.gn +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/BUILD.gn @@ -13,12 +13,22 @@ shared_library("zircon_ffi") { public_configs = [ ":zircon_ffi_config" ] sources = [ + "basic_types.cc", + "basic_types.h", + "channel.cc", + "channel.h", "clock.cc", "clock.h", + "dart_dl.cc", + "dart_dl.h", + "handle.cc", + "handle.h", + "macros.h", ] deps = [ "$fuchsia_sdk_root/pkg:zx", + "//flutter/fml", "//third_party/dart/runtime:dart_api", ] } diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/basic_types.cc b/shell/platform/fuchsia/dart-pkg/zircon_ffi/basic_types.cc new file mode 100644 index 0000000000000..32848cf14b326 --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/basic_types.cc @@ -0,0 +1,32 @@ +// 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 "basic_types.h" + +#include +#include + +#include "flutter/fml/logging.h" + +zircon_dart_byte_array_t* zircon_dart_byte_array_create(uint32_t size) { + zircon_dart_byte_array_t* arr = static_cast( + malloc(sizeof(zircon_dart_byte_array_t))); + arr->length = size; + arr->data = static_cast(malloc(size * sizeof(uint8_t))); + return arr; +} + +void zircon_dart_byte_array_set_value(zircon_dart_byte_array_t* arr, + uint32_t index, + uint8_t value) { + FML_CHECK(arr); + FML_CHECK(arr->length > index); + arr->data[index] = value; +} + +void zircon_dart_byte_array_free(zircon_dart_byte_array_t* arr) { + FML_CHECK(arr); + free(arr->data); + free(arr); +} diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/basic_types.h b/shell/platform/fuchsia/dart-pkg/zircon_ffi/basic_types.h new file mode 100644 index 0000000000000..153e77e3519f8 --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/basic_types.h @@ -0,0 +1,36 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_BASIC_TYPES_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_BASIC_TYPES_H_ + +#include "macros.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct zircon_dart_byte_array_t { + uint8_t* data; + uint32_t length; +} zircon_dart_byte_array_t; + +ZIRCON_FFI_EXPORT zircon_dart_byte_array_t* zircon_dart_byte_array_create( + uint32_t size); + +ZIRCON_FFI_EXPORT void zircon_dart_byte_array_set_value( + zircon_dart_byte_array_t* arr, + uint32_t index, + uint8_t value); + +ZIRCON_FFI_EXPORT void zircon_dart_byte_array_free( + zircon_dart_byte_array_t* arr); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_BASIC_TYPES_H_ diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/channel.cc b/shell/platform/fuchsia/dart-pkg/zircon_ffi/channel.cc new file mode 100644 index 0000000000000..b7a157cdd81ce --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/channel.cc @@ -0,0 +1,61 @@ +// 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 "channel.h" + +#include "flutter/fml/logging.h" +#include "flutter/fml/macros.h" + +#include +#include + +#include +#include + +static zircon_dart_handle_t* MakeHandle(zx_handle_t handle) { + zircon_dart_handle_t* result = + static_cast(malloc(sizeof(zircon_dart_handle_t))); + result->handle = handle; + return result; +} + +zircon_dart_handle_pair_t* zircon_dart_channel_create(uint32_t options) { + zx_handle_t out0 = 0, out1 = 0; + zx_status_t status = zx_channel_create(options, &out0, &out1); + if (status != ZX_OK) { + return nullptr; + } else { + zircon_dart_handle_pair_t* result = static_cast( + malloc(sizeof(zircon_dart_handle_pair_t))); + result->left = MakeHandle(out0); + result->right = MakeHandle(out1); + return result; + } +} + +int32_t zircon_dart_channel_write(zircon_dart_handle_t* handle, + zircon_dart_byte_array_t* bytes, + zircon_dart_handle_list_t* handles) { + if (!handle || (handle->handle == ZX_HANDLE_INVALID)) { + return ZX_ERR_BAD_HANDLE; + } + + std::vector zx_handles; + std::vector handle_data = + *reinterpret_cast*>(handles->data); + for (auto handle_ptr : handle_data) { + zx_handles.push_back(handle_ptr->handle); + } + + zx_status_t status = + zx_channel_write(handle->handle, 0, bytes->data, bytes->length, + zx_handles.data(), zx_handles.size()); + + // Handles are always consumed. + for (auto handle_ptr : handle_data) { + handle_ptr->handle = ZX_HANDLE_INVALID; + } + + return status; +} diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/channel.h b/shell/platform/fuchsia/dart-pkg/zircon_ffi/channel.h new file mode 100644 index 0000000000000..07dbcd6a01cd9 --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/channel.h @@ -0,0 +1,30 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_CHANNEL_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_CHANNEL_H_ + +#include "basic_types.h" +#include "handle.h" +#include "macros.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +ZIRCON_FFI_EXPORT zircon_dart_handle_pair_t* zircon_dart_channel_create( + uint32_t options); + +ZIRCON_FFI_EXPORT int32_t +zircon_dart_channel_write(zircon_dart_handle_t* handle, + zircon_dart_byte_array_t* bytes, + zircon_dart_handle_list_t* handles); + +#ifdef __cplusplus +} +#endif + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_CHANNEL_H_ diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/clock.h b/shell/platform/fuchsia/dart-pkg/zircon_ffi/clock.h index 275e6c00eb138..a4553deac8866 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon_ffi/clock.h +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/clock.h @@ -5,9 +5,9 @@ #ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_SDK_FFI_CLOCK_H_ #define FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_SDK_FFI_CLOCK_H_ -#include +#include "macros.h" -#define ZIRCON_FFI_EXPORT __attribute__((visibility("default"))) +#include #ifdef __cplusplus extern "C" { diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/dart_dl.cc b/shell/platform/fuchsia/dart-pkg/zircon_ffi/dart_dl.cc new file mode 100644 index 0000000000000..c6a234cdb2c5f --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/dart_dl.cc @@ -0,0 +1,17 @@ +#include "dart_dl.h" + +#include "flutter/fml/logging.h" +#include "include/dart_api_dl.h" + +int zircon_dart_dl_initialize(void* initialize_api_dl_data) { + if (Dart_InitializeApiDL(initialize_api_dl_data) != 0) { + FML_LOG(ERROR) << "Failed to initialise Dart VM API"; + return -1; + } + // Check symbols used are present + if (Dart_NewFinalizableHandle_DL == NULL) { + FML_LOG(ERROR) << "Unable to find Dart API finalizer symbols."; + return -1; + } + return 1; +} diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/dart_dl.h b/shell/platform/fuchsia/dart-pkg/zircon_ffi/dart_dl.h new file mode 100644 index 0000000000000..0bd1e06b7cc1c --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/dart_dl.h @@ -0,0 +1,24 @@ +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_DART_DL_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_DART_DL_H_ + +#include "macros.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Initialize Dart API with dynamic linking. +// +// Must be called with `NativeApi.initializeApiDLData` from `dart:ffi`, before +// using other functions. +// +// Returns 1 on success. +ZIRCON_FFI_EXPORT int zircon_dart_dl_initialize(void* initialize_api_dl_data); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_DART_DL_H_ diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/handle.cc b/shell/platform/fuchsia/dart-pkg/zircon_ffi/handle.cc new file mode 100644 index 0000000000000..4f296340b5088 --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/handle.cc @@ -0,0 +1,109 @@ +// 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 "handle.h" + +#include "flutter/fml/logging.h" + +#include +#include + +#include + +static void HandleFree(void* isolate_callback_data, void* peer) { + FML_CHECK(peer); + zircon_dart_handle_t* handle = reinterpret_cast(peer); + zircon_dart_handle_free(handle); +} + +static void HandlePairFree(void* isolate_callback_data, void* peer) { + FML_CHECK(peer); + zircon_dart_handle_pair_t* handle_pair = + reinterpret_cast(peer); + free(handle_pair); +} + +void zircon_dart_handle_free(zircon_dart_handle_t* handle) { + FML_CHECK(handle); + if (handle->handle != ZX_HANDLE_INVALID) { + zircon_dart_handle_close(handle); + } + free(handle); +} + +int32_t zircon_dart_handle_close(zircon_dart_handle_t* handle) { + FML_CHECK(handle->handle != ZX_HANDLE_INVALID); + zx_status_t status = zx_handle_close(handle->handle); + handle->handle = ZX_HANDLE_INVALID; + if (status == ZX_OK) { + return 1; + } else { + return 0; + } +} + +int32_t zircon_dart_handle_is_valid(zircon_dart_handle_t* handle) { + if (!handle || (handle->handle == ZX_HANDLE_INVALID)) { + return 0; + } else { + return 1; + } +} + +int zircon_dart_handle_attach_finalizer(Dart_Handle object, + void* pointer, + intptr_t external_allocation_size) { + Dart_FinalizableHandle weak_handle = Dart_NewFinalizableHandle_DL( + object, pointer, external_allocation_size, HandleFree); + + if (weak_handle == nullptr) { + FML_LOG(ERROR) << "Unable to attach finalizer: " << std::hex << pointer; + return -1; + } + + return 1; +} + +int zircon_dart_handle_pair_attach_finalizer( + Dart_Handle object, + void* pointer, + intptr_t external_allocation_size) { + Dart_FinalizableHandle weak_handle = Dart_NewFinalizableHandle_DL( + object, pointer, external_allocation_size, HandlePairFree); + + if (weak_handle == nullptr) { + FML_LOG(ERROR) << "Unable to attach finalizer: " << std::hex << pointer; + return -1; + } + + return 1; +} + +// zircon handle list methods. +using HandleVector = std::vector; +using HandleVectorPtr = HandleVector*; + +zircon_dart_handle_list_t* zircon_dart_handle_list_create() { + zircon_dart_handle_list_t* result = static_cast( + malloc(sizeof(zircon_dart_handle_list_t))); + result->size = 0; + result->data = new HandleVector(); + return result; +} + +void zircon_dart_handle_list_append(zircon_dart_handle_list_t* list, + zircon_dart_handle_t* handle) { + FML_CHECK(list); + FML_CHECK(handle); + list->size++; + auto data = reinterpret_cast(list->data); + data->push_back(handle); +} + +void zircon_dart_handle_list_free(zircon_dart_handle_list_t* list) { + auto data = reinterpret_cast(list->data); + data->clear(); + delete data; + free(list); +} diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/handle.h b/shell/platform/fuchsia/dart-pkg/zircon_ffi/handle.h new file mode 100644 index 0000000000000..c9248a15e8fb8 --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/handle.h @@ -0,0 +1,83 @@ +// 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. + +#ifndef SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_HANDLE_H_ +#define SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_HANDLE_H_ + +#include "macros.h" + +#include "include/dart_api_dl.h" + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct zircon_dart_handle_t { + uint32_t handle; +} zircon_dart_handle_t; + +typedef struct zircon_dart_handle_pair_t { + zircon_dart_handle_t* left; + zircon_dart_handle_t* right; +} zircon_dart_handle_pair_t; + +typedef struct zircon_dart_handle_list_t { + // data is of type `std::vector*`. + void* data; + uint32_t size; +} zircon_dart_handle_list_t; + +// Creates a list. +ZIRCON_FFI_EXPORT zircon_dart_handle_list_t* zircon_dart_handle_list_create(); + +// Appends to the list. +ZIRCON_FFI_EXPORT void zircon_dart_handle_list_append( + zircon_dart_handle_list_t* list, + zircon_dart_handle_t* handle); + +// Frees the list, all the handles passed here must have been released. +ZIRCON_FFI_EXPORT void zircon_dart_handle_list_free( + zircon_dart_handle_list_t* list); + +// Returns 1 if the handle is valid. +ZIRCON_FFI_EXPORT int32_t +zircon_dart_handle_is_valid(zircon_dart_handle_t* handle); + +// Closes the handle, but doesn't release any ffi-associated memory. Returns 1 +// on success. +ZIRCON_FFI_EXPORT int32_t +zircon_dart_handle_close(zircon_dart_handle_t* handle); + +// Closes the zircon handle if valid and frees the memory. +ZIRCON_FFI_EXPORT void zircon_dart_handle_free(zircon_dart_handle_t* handle); + +// Attach a finalizer for pointer to object, such that `finalizer(pointer)` will +// be called when `object` is collected by the Dart garbage collector. +// +// The external_allocation_size is used by the Dart garbage collector as a hint +// about the size of the external allocation. +// +// Returns 1 on success. + +ZIRCON_FFI_EXPORT int zircon_dart_handle_pair_attach_finalizer( + Dart_Handle object, + void* pointer, + intptr_t external_allocation_size); + +ZIRCON_FFI_EXPORT int zircon_dart_handle_attach_finalizer( + Dart_Handle object, + void* pointer, + intptr_t external_allocation_size); + +// ZIRCON_FFI_EXPORT zircon_dart_handle_t* zircon_dart_duplicate_handle( +// zircon_dart_handle_t* handle, +// uint32_t rights); + +#ifdef __cplusplus +} +#endif + +#endif // SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_HANDLE_H_ diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart b/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart index aae2a5a5befb7..eea6ba2a8e514 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/lib/zircon_ffi.dart @@ -19,6 +19,216 @@ class ZirconFFIBindings { lookup) : _lookup = lookup; + ffi.Pointer zircon_dart_byte_array_create( + int size, + ) { + return _zircon_dart_byte_array_create( + size, + ); + } + + late final _zircon_dart_byte_array_create_ptr = + _lookup>( + 'zircon_dart_byte_array_create'); + late final _dart_zircon_dart_byte_array_create + _zircon_dart_byte_array_create = _zircon_dart_byte_array_create_ptr + .asFunction<_dart_zircon_dart_byte_array_create>(); + + void zircon_dart_byte_array_set_value( + ffi.Pointer arr, + int index, + int value, + ) { + return _zircon_dart_byte_array_set_value( + arr, + index, + value, + ); + } + + late final _zircon_dart_byte_array_set_value_ptr = + _lookup>( + 'zircon_dart_byte_array_set_value'); + late final _dart_zircon_dart_byte_array_set_value + _zircon_dart_byte_array_set_value = _zircon_dart_byte_array_set_value_ptr + .asFunction<_dart_zircon_dart_byte_array_set_value>(); + + void zircon_dart_byte_array_free( + ffi.Pointer arr, + ) { + return _zircon_dart_byte_array_free( + arr, + ); + } + + late final _zircon_dart_byte_array_free_ptr = + _lookup>( + 'zircon_dart_byte_array_free'); + late final _dart_zircon_dart_byte_array_free _zircon_dart_byte_array_free = + _zircon_dart_byte_array_free_ptr + .asFunction<_dart_zircon_dart_byte_array_free>(); + + ffi.Pointer zircon_dart_handle_list_create() { + return _zircon_dart_handle_list_create(); + } + + late final _zircon_dart_handle_list_create_ptr = + _lookup>( + 'zircon_dart_handle_list_create'); + late final _dart_zircon_dart_handle_list_create + _zircon_dart_handle_list_create = _zircon_dart_handle_list_create_ptr + .asFunction<_dart_zircon_dart_handle_list_create>(); + + void zircon_dart_handle_list_append( + ffi.Pointer list, + ffi.Pointer handle, + ) { + return _zircon_dart_handle_list_append( + list, + handle, + ); + } + + late final _zircon_dart_handle_list_append_ptr = + _lookup>( + 'zircon_dart_handle_list_append'); + late final _dart_zircon_dart_handle_list_append + _zircon_dart_handle_list_append = _zircon_dart_handle_list_append_ptr + .asFunction<_dart_zircon_dart_handle_list_append>(); + + void zircon_dart_handle_list_free( + ffi.Pointer list, + ) { + return _zircon_dart_handle_list_free( + list, + ); + } + + late final _zircon_dart_handle_list_free_ptr = + _lookup>( + 'zircon_dart_handle_list_free'); + late final _dart_zircon_dart_handle_list_free _zircon_dart_handle_list_free = + _zircon_dart_handle_list_free_ptr + .asFunction<_dart_zircon_dart_handle_list_free>(); + + int zircon_dart_handle_is_valid( + ffi.Pointer handle, + ) { + return _zircon_dart_handle_is_valid( + handle, + ); + } + + late final _zircon_dart_handle_is_valid_ptr = + _lookup>( + 'zircon_dart_handle_is_valid'); + late final _dart_zircon_dart_handle_is_valid _zircon_dart_handle_is_valid = + _zircon_dart_handle_is_valid_ptr + .asFunction<_dart_zircon_dart_handle_is_valid>(); + + int zircon_dart_handle_close( + ffi.Pointer handle, + ) { + return _zircon_dart_handle_close( + handle, + ); + } + + late final _zircon_dart_handle_close_ptr = + _lookup>( + 'zircon_dart_handle_close'); + late final _dart_zircon_dart_handle_close _zircon_dart_handle_close = + _zircon_dart_handle_close_ptr + .asFunction<_dart_zircon_dart_handle_close>(); + + void zircon_dart_handle_free( + ffi.Pointer handle, + ) { + return _zircon_dart_handle_free( + handle, + ); + } + + late final _zircon_dart_handle_free_ptr = + _lookup>( + 'zircon_dart_handle_free'); + late final _dart_zircon_dart_handle_free _zircon_dart_handle_free = + _zircon_dart_handle_free_ptr.asFunction<_dart_zircon_dart_handle_free>(); + + int zircon_dart_handle_pair_attach_finalizer( + Object object, + ffi.Pointer pointer, + int external_allocation_size, + ) { + return _zircon_dart_handle_pair_attach_finalizer( + object, + pointer, + external_allocation_size, + ); + } + + late final _zircon_dart_handle_pair_attach_finalizer_ptr = + _lookup>( + 'zircon_dart_handle_pair_attach_finalizer'); + late final _dart_zircon_dart_handle_pair_attach_finalizer + _zircon_dart_handle_pair_attach_finalizer = + _zircon_dart_handle_pair_attach_finalizer_ptr + .asFunction<_dart_zircon_dart_handle_pair_attach_finalizer>(); + + int zircon_dart_handle_attach_finalizer( + Object object, + ffi.Pointer pointer, + int external_allocation_size, + ) { + return _zircon_dart_handle_attach_finalizer( + object, + pointer, + external_allocation_size, + ); + } + + late final _zircon_dart_handle_attach_finalizer_ptr = + _lookup>( + 'zircon_dart_handle_attach_finalizer'); + late final _dart_zircon_dart_handle_attach_finalizer + _zircon_dart_handle_attach_finalizer = + _zircon_dart_handle_attach_finalizer_ptr + .asFunction<_dart_zircon_dart_handle_attach_finalizer>(); + + ffi.Pointer zircon_dart_channel_create( + int options, + ) { + return _zircon_dart_channel_create( + options, + ); + } + + late final _zircon_dart_channel_create_ptr = + _lookup>( + 'zircon_dart_channel_create'); + late final _dart_zircon_dart_channel_create _zircon_dart_channel_create = + _zircon_dart_channel_create_ptr + .asFunction<_dart_zircon_dart_channel_create>(); + + int zircon_dart_channel_write( + ffi.Pointer handle, + ffi.Pointer bytes, + ffi.Pointer handles, + ) { + return _zircon_dart_channel_write( + handle, + bytes, + handles, + ); + } + + late final _zircon_dart_channel_write_ptr = + _lookup>( + 'zircon_dart_channel_write'); + late final _dart_zircon_dart_channel_write _zircon_dart_channel_write = + _zircon_dart_channel_write_ptr + .asFunction<_dart_zircon_dart_channel_write>(); + int zircon_dart_clock_get_monotonic() { return _zircon_dart_clock_get_monotonic(); } @@ -29,8 +239,182 @@ class ZirconFFIBindings { late final _dart_zircon_dart_clock_get_monotonic _zircon_dart_clock_get_monotonic = _zircon_dart_clock_get_monotonic_ptr .asFunction<_dart_zircon_dart_clock_get_monotonic>(); + + int zircon_dart_dl_initialize( + ffi.Pointer initialize_api_dl_data, + ) { + return _zircon_dart_dl_initialize( + initialize_api_dl_data, + ); + } + + late final _zircon_dart_dl_initialize_ptr = + _lookup>( + 'zircon_dart_dl_initialize'); + late final _dart_zircon_dart_dl_initialize _zircon_dart_dl_initialize = + _zircon_dart_dl_initialize_ptr + .asFunction<_dart_zircon_dart_dl_initialize>(); +} + +class zircon_dart_byte_array_t extends ffi.Struct { + external ffi.Pointer data; + + @ffi.Uint32() + external int length; +} + +class zircon_dart_handle_t extends ffi.Struct { + @ffi.Uint32() + external int handle; } +class zircon_dart_handle_pair_t extends ffi.Struct { + external ffi.Pointer left; + + external ffi.Pointer right; +} + +class zircon_dart_handle_list_t extends ffi.Struct { + external ffi.Pointer data; + + @ffi.Uint32() + external int size; +} + +class _Dart_Handle extends ffi.Opaque {} + +typedef _c_zircon_dart_byte_array_create = ffi.Pointer + Function( + ffi.Uint32 size, +); + +typedef _dart_zircon_dart_byte_array_create + = ffi.Pointer Function( + int size, +); + +typedef _c_zircon_dart_byte_array_set_value = ffi.Void Function( + ffi.Pointer arr, + ffi.Uint32 index, + ffi.Uint8 value, +); + +typedef _dart_zircon_dart_byte_array_set_value = void Function( + ffi.Pointer arr, + int index, + int value, +); + +typedef _c_zircon_dart_byte_array_free = ffi.Void Function( + ffi.Pointer arr, +); + +typedef _dart_zircon_dart_byte_array_free = void Function( + ffi.Pointer arr, +); + +typedef _c_zircon_dart_handle_list_create + = ffi.Pointer Function(); + +typedef _dart_zircon_dart_handle_list_create + = ffi.Pointer Function(); + +typedef _c_zircon_dart_handle_list_append = ffi.Void Function( + ffi.Pointer list, + ffi.Pointer handle, +); + +typedef _dart_zircon_dart_handle_list_append = void Function( + ffi.Pointer list, + ffi.Pointer handle, +); + +typedef _c_zircon_dart_handle_list_free = ffi.Void Function( + ffi.Pointer list, +); + +typedef _dart_zircon_dart_handle_list_free = void Function( + ffi.Pointer list, +); + +typedef _c_zircon_dart_handle_is_valid = ffi.Int32 Function( + ffi.Pointer handle, +); + +typedef _dart_zircon_dart_handle_is_valid = int Function( + ffi.Pointer handle, +); + +typedef _c_zircon_dart_handle_close = ffi.Int32 Function( + ffi.Pointer handle, +); + +typedef _dart_zircon_dart_handle_close = int Function( + ffi.Pointer handle, +); + +typedef _c_zircon_dart_handle_free = ffi.Void Function( + ffi.Pointer handle, +); + +typedef _dart_zircon_dart_handle_free = void Function( + ffi.Pointer handle, +); + +typedef _c_zircon_dart_handle_pair_attach_finalizer = ffi.Int32 Function( + ffi.Handle object, + ffi.Pointer pointer, + ffi.IntPtr external_allocation_size, +); + +typedef _dart_zircon_dart_handle_pair_attach_finalizer = int Function( + Object object, + ffi.Pointer pointer, + int external_allocation_size, +); + +typedef _c_zircon_dart_handle_attach_finalizer = ffi.Int32 Function( + ffi.Handle object, + ffi.Pointer pointer, + ffi.IntPtr external_allocation_size, +); + +typedef _dart_zircon_dart_handle_attach_finalizer = int Function( + Object object, + ffi.Pointer pointer, + int external_allocation_size, +); + +typedef _c_zircon_dart_channel_create = ffi.Pointer + Function( + ffi.Uint32 options, +); + +typedef _dart_zircon_dart_channel_create + = ffi.Pointer Function( + int options, +); + +typedef _c_zircon_dart_channel_write = ffi.Int32 Function( + ffi.Pointer handle, + ffi.Pointer bytes, + ffi.Pointer handles, +); + +typedef _dart_zircon_dart_channel_write = int Function( + ffi.Pointer handle, + ffi.Pointer bytes, + ffi.Pointer handles, +); + typedef _c_zircon_dart_clock_get_monotonic = ffi.Uint64 Function(); typedef _dart_zircon_dart_clock_get_monotonic = int Function(); + +typedef _c_zircon_dart_dl_initialize = ffi.Int32 Function( + ffi.Pointer initialize_api_dl_data, +); + +typedef _dart_zircon_dart_dl_initialize = int Function( + ffi.Pointer initialize_api_dl_data, +); diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/macros.h b/shell/platform/fuchsia/dart-pkg/zircon_ffi/macros.h new file mode 100644 index 0000000000000..7c78e0d6e3d3d --- /dev/null +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/macros.h @@ -0,0 +1,10 @@ +// 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. + +#ifndef FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_MACROS_H_ +#define FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_MACROS_H_ + +#define ZIRCON_FFI_EXPORT __attribute__((visibility("default"))) + +#endif // FLUTTER_SHELL_PLATFORM_FUCHSIA_DART_PKG_ZIRCON_FFI_MACROS_H_ diff --git a/shell/platform/fuchsia/dart-pkg/zircon_ffi/pubspec.yaml b/shell/platform/fuchsia/dart-pkg/zircon_ffi/pubspec.yaml index fac6b53c18886..51113aa82fdd2 100644 --- a/shell/platform/fuchsia/dart-pkg/zircon_ffi/pubspec.yaml +++ b/shell/platform/fuchsia/dart-pkg/zircon_ffi/pubspec.yaml @@ -16,7 +16,11 @@ ffigen: output: 'lib/zircon_ffi.dart' headers: entry-points: + - 'basic_types.h' + - 'channel.h' - 'clock.h' + - 'dart_dl.h' + - 'handle.h' functions: include: - 'zircon_dart_.*' @@ -34,7 +38,7 @@ ffigen: - nothing structs: include: - - nothing + - 'zircon_dart_.*' dependency-only: opaque compiler-opts: - - '-I../../../../../../../third_party/dart/runtime' + - '-I../../../../../../third_party/dart/runtime'