From c990db091340487191dbf9cdb0fc0390a13bd953 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Tue, 31 Oct 2023 15:27:23 -0600 Subject: [PATCH] Ladybird/Android: Create a service for ImageDecoder This follows the pattern for the other services spawned by WebContent. The notable quirk about this service is that it's actually spawned by the ImageCodecPlugin rather than in main.cpp in the non-Android port. As a result we needed to do some ifdef surgery to get all the pieces in place. But we can now load images in the Android port again :^). --- Ladybird/Android/src/main/AndroidManifest.xml | 5 +++++ .../src/main/cpp/ImageDecoderService.cpp | 22 +++++++++++++++++++ .../src/main/cpp/WebContentService.cpp | 5 +++++ .../Android/src/main/cpp/WebContentService.h | 1 + .../src/main/cpp/WebContentServiceJNI.cpp | 12 ++++++++++ .../ladybird/ImageDecoderService.kt | 21 ++++++++++++++++++ .../serenityos/ladybird/WebContentService.kt | 17 +++++++++++++- Ladybird/ImageCodecPlugin.cpp | 10 ++++++++- Ladybird/ImageDecoder/CMakeLists.txt | 21 +++++++++++++----- Ladybird/WebContent/CMakeLists.txt | 2 +- 10 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 Ladybird/Android/src/main/cpp/ImageDecoderService.cpp create mode 100644 Ladybird/Android/src/main/java/org/serenityos/ladybird/ImageDecoderService.kt diff --git a/Ladybird/Android/src/main/AndroidManifest.xml b/Ladybird/Android/src/main/AndroidManifest.xml index c654cc0cb0..bcf49bc8a0 100644 --- a/Ladybird/Android/src/main/AndroidManifest.xml +++ b/Ladybird/Android/src/main/AndroidManifest.xml @@ -61,6 +61,11 @@ android:enabled="true" android:exported="false" android:process=":WebSocket" /> + diff --git a/Ladybird/Android/src/main/cpp/ImageDecoderService.cpp b/Ladybird/Android/src/main/cpp/ImageDecoderService.cpp new file mode 100644 index 0000000000..1086a6e2b9 --- /dev/null +++ b/Ladybird/Android/src/main/cpp/ImageDecoderService.cpp @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018-2020, Andreas Kling + * Copyright (c) 2023, Andrew Kaster + * Copyright (c) 2023, Lucas Chollet + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include + +ErrorOr service_main(int ipc_socket, int fd_passing_socket) +{ + Core::EventLoop event_loop; + + auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket)); + auto client = TRY(ImageDecoder::ConnectionFromClient::try_create(move(socket))); + client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket))); + + return event_loop.exec(); +} diff --git a/Ladybird/Android/src/main/cpp/WebContentService.cpp b/Ladybird/Android/src/main/cpp/WebContentService.cpp index 637c56f408..b0f10d7174 100644 --- a/Ladybird/Android/src/main/cpp/WebContentService.cpp +++ b/Ladybird/Android/src/main/cpp/WebContentService.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,11 @@ static ErrorOr> bind_web_socket_service return bind_service(&bind_web_socket_java); } +template ErrorOr, Error> +bind_service(void (*)(int, int)); + static ErrorOr load_content_filters(); + static ErrorOr load_autoplay_allowlist(); ErrorOr service_main(int ipc_socket, int fd_passing_socket) diff --git a/Ladybird/Android/src/main/cpp/WebContentService.h b/Ladybird/Android/src/main/cpp/WebContentService.h index 9e570ab26c..ab67091ca1 100644 --- a/Ladybird/Android/src/main/cpp/WebContentService.h +++ b/Ladybird/Android/src/main/cpp/WebContentService.h @@ -13,3 +13,4 @@ ErrorOr> bind_service(void (*bind_method)(int, int)); void bind_request_server_java(int ipc_socket, int fd_passing_socket); void bind_web_socket_java(int ipc_socket, int fd_passing_socket); +void bind_image_decoder_java(int ipc_socket, int fd_passing_socket); diff --git a/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp b/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp index e4b4ae8dc3..e050bbb673 100644 --- a/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp +++ b/Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp @@ -12,6 +12,7 @@ jobject global_instance; jclass global_class_reference; jmethodID bind_request_server_method; jmethodID bind_web_socket_method; +jmethodID bind_image_decoder_method; extern "C" JNIEXPORT void JNICALL Java_org_serenityos_ladybird_WebContentService_nativeInit(JNIEnv* env, jobject thiz) @@ -33,6 +34,11 @@ Java_org_serenityos_ladybird_WebContentService_nativeInit(JNIEnv* env, jobject t if (!method) TODO(); bind_web_socket_method = method; + + method = env->GetMethodID(global_class_reference, "bindImageDecoder", "(II)V"); + if (!method) + TODO(); + bind_image_decoder_method = method; } void bind_request_server_java(int ipc_socket, int fd_passing_socket) @@ -46,3 +52,9 @@ void bind_web_socket_java(int ipc_socket, int fd_passing_socket) Ladybird::JavaEnvironment env(global_vm); env.get()->CallVoidMethod(global_instance, bind_web_socket_method, ipc_socket, fd_passing_socket); } + +void bind_image_decoder_java(int ipc_socket, int fd_passing_socket) +{ + Ladybird::JavaEnvironment env(global_vm); + env.get()->CallVoidMethod(global_instance, bind_image_decoder_method, ipc_socket, fd_passing_socket); +} diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/ImageDecoderService.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/ImageDecoderService.kt new file mode 100644 index 0000000000..1c5e1cb522 --- /dev/null +++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/ImageDecoderService.kt @@ -0,0 +1,21 @@ +/** + * Copyright (c) 2023, Andrew Kaster + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +package org.serenityos.ladybird + +import android.os.Message + +class ImageDecoderService : LadybirdServiceBase("ImageDecoderService") { + override fun handleServiceSpecificMessage(msg: Message): Boolean { + return false + } + + companion object { + init { + System.loadLibrary("imagedecoder") + } + } +} diff --git a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt index 705445a236..0108808b9e 100644 --- a/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt +++ b/Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt @@ -40,7 +40,7 @@ class WebContentService : LadybirdServiceBase("WebContentService") { val connector = LadybirdServiceConnection(ipcFd, fdPassingFd, resourceDir) connector.onDisconnect = { // FIXME: Notify impl that service is dead and might need restarted - Log.e(TAG, "RequestServer Died! :(") + Log.e(TAG, "WebSocket Died! :(") } // FIXME: Unbind this at some point maybe bindService( @@ -50,6 +50,21 @@ class WebContentService : LadybirdServiceBase("WebContentService") { ) } + private fun bindImageDecoder(ipcFd: Int, fdPassingFd: Int) + { + val connector = LadybirdServiceConnection(ipcFd, fdPassingFd, resourceDir) + connector.onDisconnect = { + // FIXME: Notify impl that service is dead and might need restarted + Log.e(TAG, "ImageDecoder Died! :(") + } + // FIXME: Unbind this at some point maybe + bindService( + Intent(this, ImageDecoderService::class.java), + connector, + Context.BIND_AUTO_CREATE + ) + } + external fun nativeInit() companion object { diff --git a/Ladybird/ImageCodecPlugin.cpp b/Ladybird/ImageCodecPlugin.cpp index 95d8c38e59..b10155f1be 100644 --- a/Ladybird/ImageCodecPlugin.cpp +++ b/Ladybird/ImageCodecPlugin.cpp @@ -6,7 +6,11 @@ */ #include "ImageCodecPlugin.h" -#include "HelperProcess.h" +#ifdef AK_OS_ANDROID +# include +#else +# include "HelperProcess.h" +#endif #include "Utilities.h" #include #include @@ -19,8 +23,12 @@ ImageCodecPlugin::~ImageCodecPlugin() = default; Optional ImageCodecPlugin::decode_image(ReadonlyBytes bytes) { if (!m_client) { +#ifdef AK_OS_ANDROID + m_client = MUST(bind_service(&bind_image_decoder_java)); +#else auto candidate_image_decoder_paths = get_paths_for_helper_process("ImageDecoder"sv).release_value_but_fixme_should_propagate_errors(); m_client = launch_image_decoder_process(candidate_image_decoder_paths).release_value_but_fixme_should_propagate_errors(); +#endif m_client->on_death = [&] { m_client = nullptr; }; diff --git a/Ladybird/ImageDecoder/CMakeLists.txt b/Ladybird/ImageDecoder/CMakeLists.txt index a1eca1f9f9..ac506d5a8c 100644 --- a/Ladybird/ImageDecoder/CMakeLists.txt +++ b/Ladybird/ImageDecoder/CMakeLists.txt @@ -2,11 +2,22 @@ set(IMAGE_DECODER_SOURCE_DIR ${SERENITY_SOURCE_DIR}/Userland/Services/ImageDecod set(IMAGE_DECODER_SOURCES ${IMAGE_DECODER_SOURCE_DIR}/ConnectionFromClient.cpp - main.cpp ) -add_executable(ImageDecoder ${IMAGE_DECODER_SOURCES}) +if (ANDROID) + add_library(imagedecoder SHARED + ${IMAGE_DECODER_SOURCES} + ../Android/src/main/cpp/ImageDecoderService.cpp + ../Android/src/main/cpp/LadybirdServiceBaseJNI.cpp + ../Utilities.cpp + ) +else() + add_library(imagedecoder STATIC ${IMAGE_DECODER_SOURCES}) +endif() -target_include_directories(ImageDecoder PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/) -target_include_directories(ImageDecoder PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..) -target_link_libraries(ImageDecoder PRIVATE LibCore LibGfx LibIPC LibImageDecoderClient LibMain) +add_executable(ImageDecoder main.cpp) +target_link_libraries(ImageDecoder PRIVATE imagedecoder LibMain) + +target_include_directories(imagedecoder PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/) +target_include_directories(imagedecoder PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..) +target_link_libraries(imagedecoder PRIVATE LibCore LibGfx LibIPC LibImageDecoderClient LibMain) diff --git a/Ladybird/WebContent/CMakeLists.txt b/Ladybird/WebContent/CMakeLists.txt index 2ac635007a..89efdb394c 100644 --- a/Ladybird/WebContent/CMakeLists.txt +++ b/Ladybird/WebContent/CMakeLists.txt @@ -37,7 +37,7 @@ else() add_library(webcontent ${LIB_TYPE} ${WEBCONTENT_SOURCES}) target_include_directories(webcontent PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/) target_include_directories(webcontent PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..) - target_link_libraries(webcontent PRIVATE LibAudio LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket LibProtocol LibWebView) + target_link_libraries(webcontent PRIVATE LibAudio LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket LibProtocol LibWebView LibImageDecoderClient) target_sources(webcontent PUBLIC FILE_SET ladybird TYPE HEADERS BASE_DIRS ${SERENITY_SOURCE_DIR} FILES ../FontPlugin.h