Skip to content

Commit c990db0

Browse files
committed
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 :^).
1 parent a54baa2 commit c990db0

File tree

10 files changed

+108
-8
lines changed

10 files changed

+108
-8
lines changed

Ladybird/Android/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@
6161
android:enabled="true"
6262
android:exported="false"
6363
android:process=":WebSocket" />
64+
<service
65+
android:name=".ImageDecoderService"
66+
android:enabled="true"
67+
android:exported="false"
68+
android:process=":ImageDecoder" />
6469
</application>
6570

6671
</manifest>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/*
2+
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3+
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
4+
* Copyright (c) 2023, Lucas Chollet <lucas.chollet@serenityos.org>
5+
*
6+
* SPDX-License-Identifier: BSD-2-Clause
7+
*/
8+
9+
#include <ImageDecoder/ConnectionFromClient.h>
10+
#include <LibCore/EventLoop.h>
11+
#include <LibIPC/SingleServer.h>
12+
13+
ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket)
14+
{
15+
Core::EventLoop event_loop;
16+
17+
auto socket = TRY(Core::LocalSocket::adopt_fd(ipc_socket));
18+
auto client = TRY(ImageDecoder::ConnectionFromClient::try_create(move(socket)));
19+
client->set_fd_passing_socket(TRY(Core::LocalSocket::adopt_fd(fd_passing_socket)));
20+
21+
return event_loop.exec();
22+
}

Ladybird/Android/src/main/cpp/WebContentService.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include <LibCore/LocalServer.h>
1818
#include <LibCore/System.h>
1919
#include <LibIPC/ConnectionFromClient.h>
20+
#include <LibImageDecoderClient/Client.h>
2021
#include <LibJS/Bytecode/Interpreter.h>
2122
#include <LibWeb/Bindings/MainThreadVM.h>
2223
#include <LibWeb/HTML/Window.h>
@@ -41,7 +42,11 @@ static ErrorOr<NonnullRefPtr<Protocol::WebSocketClient>> bind_web_socket_service
4142
return bind_service<Protocol::WebSocketClient>(&bind_web_socket_java);
4243
}
4344

45+
template ErrorOr<NonnullRefPtr<ImageDecoderClient::Client>, Error>
46+
bind_service<ImageDecoderClient::Client>(void (*)(int, int));
47+
4448
static ErrorOr<void> load_content_filters();
49+
4550
static ErrorOr<void> load_autoplay_allowlist();
4651

4752
ErrorOr<int> service_main(int ipc_socket, int fd_passing_socket)

Ladybird/Android/src/main/cpp/WebContentService.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ ErrorOr<NonnullRefPtr<Client>> bind_service(void (*bind_method)(int, int));
1313

1414
void bind_request_server_java(int ipc_socket, int fd_passing_socket);
1515
void bind_web_socket_java(int ipc_socket, int fd_passing_socket);
16+
void bind_image_decoder_java(int ipc_socket, int fd_passing_socket);

Ladybird/Android/src/main/cpp/WebContentServiceJNI.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jobject global_instance;
1212
jclass global_class_reference;
1313
jmethodID bind_request_server_method;
1414
jmethodID bind_web_socket_method;
15+
jmethodID bind_image_decoder_method;
1516

1617
extern "C" JNIEXPORT void JNICALL
1718
Java_org_serenityos_ladybird_WebContentService_nativeInit(JNIEnv* env, jobject thiz)
@@ -33,6 +34,11 @@ Java_org_serenityos_ladybird_WebContentService_nativeInit(JNIEnv* env, jobject t
3334
if (!method)
3435
TODO();
3536
bind_web_socket_method = method;
37+
38+
method = env->GetMethodID(global_class_reference, "bindImageDecoder", "(II)V");
39+
if (!method)
40+
TODO();
41+
bind_image_decoder_method = method;
3642
}
3743

3844
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)
4652
Ladybird::JavaEnvironment env(global_vm);
4753
env.get()->CallVoidMethod(global_instance, bind_web_socket_method, ipc_socket, fd_passing_socket);
4854
}
55+
56+
void bind_image_decoder_java(int ipc_socket, int fd_passing_socket)
57+
{
58+
Ladybird::JavaEnvironment env(global_vm);
59+
env.get()->CallVoidMethod(global_instance, bind_image_decoder_method, ipc_socket, fd_passing_socket);
60+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Copyright (c) 2023, Andrew Kaster <akaster@serenityos.org>
3+
*
4+
* SPDX-License-Identifier: BSD-2-Clause
5+
*/
6+
7+
package org.serenityos.ladybird
8+
9+
import android.os.Message
10+
11+
class ImageDecoderService : LadybirdServiceBase("ImageDecoderService") {
12+
override fun handleServiceSpecificMessage(msg: Message): Boolean {
13+
return false
14+
}
15+
16+
companion object {
17+
init {
18+
System.loadLibrary("imagedecoder")
19+
}
20+
}
21+
}

Ladybird/Android/src/main/java/org/serenityos/ladybird/WebContentService.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class WebContentService : LadybirdServiceBase("WebContentService") {
4040
val connector = LadybirdServiceConnection(ipcFd, fdPassingFd, resourceDir)
4141
connector.onDisconnect = {
4242
// FIXME: Notify impl that service is dead and might need restarted
43-
Log.e(TAG, "RequestServer Died! :(")
43+
Log.e(TAG, "WebSocket Died! :(")
4444
}
4545
// FIXME: Unbind this at some point maybe
4646
bindService(
@@ -50,6 +50,21 @@ class WebContentService : LadybirdServiceBase("WebContentService") {
5050
)
5151
}
5252

53+
private fun bindImageDecoder(ipcFd: Int, fdPassingFd: Int)
54+
{
55+
val connector = LadybirdServiceConnection(ipcFd, fdPassingFd, resourceDir)
56+
connector.onDisconnect = {
57+
// FIXME: Notify impl that service is dead and might need restarted
58+
Log.e(TAG, "ImageDecoder Died! :(")
59+
}
60+
// FIXME: Unbind this at some point maybe
61+
bindService(
62+
Intent(this, ImageDecoderService::class.java),
63+
connector,
64+
Context.BIND_AUTO_CREATE
65+
)
66+
}
67+
5368
external fun nativeInit()
5469

5570
companion object {

Ladybird/ImageCodecPlugin.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
*/
77

88
#include "ImageCodecPlugin.h"
9-
#include "HelperProcess.h"
9+
#ifdef AK_OS_ANDROID
10+
# include <Ladybird/Android/src/main/cpp/WebContentService.h>
11+
#else
12+
# include "HelperProcess.h"
13+
#endif
1014
#include "Utilities.h"
1115
#include <LibGfx/Bitmap.h>
1216
#include <LibGfx/ImageFormats/ImageDecoder.h>
@@ -19,8 +23,12 @@ ImageCodecPlugin::~ImageCodecPlugin() = default;
1923
Optional<Web::Platform::DecodedImage> ImageCodecPlugin::decode_image(ReadonlyBytes bytes)
2024
{
2125
if (!m_client) {
26+
#ifdef AK_OS_ANDROID
27+
m_client = MUST(bind_service<ImageDecoderClient::Client>(&bind_image_decoder_java));
28+
#else
2229
auto candidate_image_decoder_paths = get_paths_for_helper_process("ImageDecoder"sv).release_value_but_fixme_should_propagate_errors();
2330
m_client = launch_image_decoder_process(candidate_image_decoder_paths).release_value_but_fixme_should_propagate_errors();
31+
#endif
2432
m_client->on_death = [&] {
2533
m_client = nullptr;
2634
};

Ladybird/ImageDecoder/CMakeLists.txt

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,22 @@ set(IMAGE_DECODER_SOURCE_DIR ${SERENITY_SOURCE_DIR}/Userland/Services/ImageDecod
22

33
set(IMAGE_DECODER_SOURCES
44
${IMAGE_DECODER_SOURCE_DIR}/ConnectionFromClient.cpp
5-
main.cpp
65
)
76

8-
add_executable(ImageDecoder ${IMAGE_DECODER_SOURCES})
7+
if (ANDROID)
8+
add_library(imagedecoder SHARED
9+
${IMAGE_DECODER_SOURCES}
10+
../Android/src/main/cpp/ImageDecoderService.cpp
11+
../Android/src/main/cpp/LadybirdServiceBaseJNI.cpp
12+
../Utilities.cpp
13+
)
14+
else()
15+
add_library(imagedecoder STATIC ${IMAGE_DECODER_SOURCES})
16+
endif()
917

10-
target_include_directories(ImageDecoder PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
11-
target_include_directories(ImageDecoder PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
12-
target_link_libraries(ImageDecoder PRIVATE LibCore LibGfx LibIPC LibImageDecoderClient LibMain)
18+
add_executable(ImageDecoder main.cpp)
19+
target_link_libraries(ImageDecoder PRIVATE imagedecoder LibMain)
20+
21+
target_include_directories(imagedecoder PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
22+
target_include_directories(imagedecoder PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
23+
target_link_libraries(imagedecoder PRIVATE LibCore LibGfx LibIPC LibImageDecoderClient LibMain)

Ladybird/WebContent/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ else()
3737
add_library(webcontent ${LIB_TYPE} ${WEBCONTENT_SOURCES})
3838
target_include_directories(webcontent PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/)
3939
target_include_directories(webcontent PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..)
40-
target_link_libraries(webcontent PRIVATE LibAudio LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket LibProtocol LibWebView)
40+
target_link_libraries(webcontent PRIVATE LibAudio LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket LibProtocol LibWebView LibImageDecoderClient)
4141
target_sources(webcontent PUBLIC FILE_SET ladybird TYPE HEADERS
4242
BASE_DIRS ${SERENITY_SOURCE_DIR}
4343
FILES ../FontPlugin.h

0 commit comments

Comments
 (0)