Skip to content

Commit

Permalink
[JNI Example] Call native in Java (#4657)
Browse files Browse the repository at this point in the history
This PR serves as an example of how we should migrate Java native API to
Chromium JNI standard.

Local test: 
Simply ensure the native API is invoked.
haozheng@haozheng:~/chromium/src$ adb logcat | grep JNI
01-08 14:56:20.158 13226 13226 I starboard:
[dev.cobalt.coat/13226:0108/225620.158117(UTC):INFO:starboard_bridge.cc(93)]
JNI: StartNativeStarboard: 0xec140a60

Explanation:
Replace
Java_dev_cobalt_coat_StarboardBridge_startNativeStarboard(JniEnvExt*
env) with JNI_StarboardBridge_StartNativeStarboard(JNIEnv* env).
Move implementation over to starboard_bridge.cc because we should only
include the _jni header from a single .cc file as the header defines
functions, to avoid duplicate symbols issue.

b/372559388
  • Loading branch information
haozheng-cobalt authored Jan 9, 2025
1 parent c99e348 commit 632168a
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -131,13 +131,11 @@ public StarboardBridge(
this.volumeStateReceiver = new VolumeStateReceiver(appContext);
this.isAmatiDevice = appContext.getPackageManager().hasSystemFeature(AMATI_EXPERIENCE_FEATURE);

nativeApp = startNativeStarboard();
nativeApp = StarboardBridgeJni.get().startNativeStarboard();
}

private native boolean initJNI();

private native long startNativeStarboard();

private native void closeNativeStarboard(long nativeApp);

@NativeMethods
Expand All @@ -146,11 +144,10 @@ interface Natives {

long currentMonotonicTime();

long startNativeStarboard();
// TODO(cobalt, b/372559388): move below native methods to the Natives interface.
// boolean initJNI();

// long startNativeStarboard();

// void closeNativeStarboard(long nativeApp);
}

Expand Down
51 changes: 0 additions & 51 deletions starboard/android/shared/android_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include "starboard/event.h"
#include "starboard/log.h"
#include "starboard/shared/starboard/command_line.h"
#include "starboard/shared/starboard/log_mutex.h"
#include "starboard/thread.h"
#if SB_IS(EVERGREEN_COMPATIBLE)
#include "starboard/crashpad_wrapper/wrapper.h" // nogncheck
Expand Down Expand Up @@ -59,17 +58,6 @@ Semaphore* g_app_created_semaphore = nullptr;
std::atomic_bool g_app_running{false};
#endif // SB_IS(EVERGREEN_COMPATIBLE)

std::vector<std::string> GetArgs() {
std::vector<std::string> args;
// Fake program name as args[0]
args.push_back("android_main");

JNIEnv* env = base::android::AttachCurrentThread();
StarboardBridge::GetInstance()->AppendArgs(env, &args);

return args;
}

#if SB_IS(EVERGREEN_COMPATIBLE)
bool CopyDirContents(const std::string& src_dir_path,
const std::string& dst_dir_path) {
Expand Down Expand Up @@ -242,30 +230,6 @@ Java_dev_cobalt_coat_StarboardBridge_nativeIsReleaseBuild() {
#endif
}

#if SB_IS(EVERGREEN_COMPATIBLE)
void StarboardThreadLaunch() {
// Start the Starboard thread the first time an Activity is created.
if (g_starboard_thread == 0) {
Semaphore semaphore;

pthread_attr_t attributes;
pthread_attr_init(&attributes);
pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);

pthread_create(&g_starboard_thread, &attributes, &ThreadEntryPoint,
&semaphore);

pthread_attr_destroy(&attributes);

// Wait for the ApplicationAndroid to be created.
semaphore.Take();
}

// Ensure application init happens here
ApplicationAndroid::Get();
}
#endif // SB_IS(EVERGREEN_COMPATIBLE)

// TODO(cobalt, b/372559388): consolidate this function when fully deprecate
// JniEnvExt.
extern "C" SB_EXPORT_PLATFORM void Java_dev_cobalt_coat_StarboardBridge_initJNI(
Expand All @@ -278,21 +242,6 @@ extern "C" SB_EXPORT_PLATFORM void Java_dev_cobalt_coat_StarboardBridge_initJNI(
StarboardBridge::GetInstance()->Initialize(jni_env, starboard_bridge);
}

extern "C" SB_EXPORT_PLATFORM jlong
Java_dev_cobalt_coat_StarboardBridge_startNativeStarboard(JniEnvExt* env) {
#if SB_IS(EVERGREEN_COMPATIBLE)
StarboardThreadLaunch();
#else
starboard::shared::starboard::GetLoggingMutex();
auto command_line = std::make_unique<CommandLine>(GetArgs());
LogInit(*command_line);
auto* nativeApp = new ApplicationAndroid(std::move(command_line));
// Ensure application init happens here
ApplicationAndroid::Get();
return reinterpret_cast<jlong>(nativeApp);
#endif // SB_IS(EVERGREEN_COMPATIBLE)
}

extern "C" SB_EXPORT_PLATFORM void
Java_dev_cobalt_coat_StarboardBridge_closeNativeStarboard(JniEnvExt* env,
jlong nativeApp) {
Expand Down
56 changes: 56 additions & 0 deletions starboard/android/shared/starboard_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,15 @@

#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "starboard/android/shared/application_android.h"
#include "starboard/android/shared/file_internal.h"
#include "starboard/android/shared/log_internal.h"
#include "starboard/common/log.h"
#include "starboard/common/time.h"
#include "starboard/media.h"
#include "starboard/shared/starboard/audio_sink/audio_sink_internal.h"
#include "starboard/shared/starboard/command_line.h"
#include "starboard/shared/starboard/log_mutex.h"

// Must come after all headers that specialize FromJniType() / ToJniType().
#include "cobalt/android/jni_headers/StarboardBridge_jni.h"
Expand All @@ -29,6 +33,43 @@ namespace starboard {
namespace android {
namespace shared {

namespace {
#if SB_IS(EVERGREEN_COMPATIBLE)
void StarboardThreadLaunch() {
// Start the Starboard thread the first time an Activity is created.
if (g_starboard_thread == 0) {
Semaphore semaphore;

pthread_attr_t attributes;
pthread_attr_init(&attributes);
pthread_attr_setdetachstate(&attributes, PTHREAD_CREATE_DETACHED);

pthread_create(&g_starboard_thread, &attributes, &ThreadEntryPoint,
&semaphore);

pthread_attr_destroy(&attributes);

// Wait for the ApplicationAndroid to be created.
semaphore.Take();
}

// Ensure application init happens here
ApplicationAndroid::Get();
}
#endif // SB_IS(EVERGREEN_COMPATIBLE)
} // namespace

std::vector<std::string> GetArgs() {
std::vector<std::string> args;
// Fake program name as args[0]
args.push_back("android_main");

JNIEnv* env = base::android::AttachCurrentThread();
StarboardBridge::GetInstance()->AppendArgs(env, &args);

return args;
}

extern "C" SB_EXPORT_PLATFORM void JNI_StarboardBridge_OnStop(JNIEnv* env) {
::starboard::shared::starboard::audio_sink::SbAudioSinkImpl::TearDown();
SbFileAndroidTeardown();
Expand All @@ -39,6 +80,21 @@ JNI_StarboardBridge_CurrentMonotonicTime(JNIEnv* env) {
return CurrentMonotonicTime();
}

extern "C" SB_EXPORT_PLATFORM jlong
JNI_StarboardBridge_StartNativeStarboard(JNIEnv* env) {
#if SB_IS(EVERGREEN_COMPATIBLE)
StarboardThreadLaunch();
#else
starboard::shared::starboard::GetLoggingMutex();
auto command_line = std::make_unique<CommandLine>(GetArgs());
LogInit(*command_line);
auto* nativeApp = new ApplicationAndroid(std::move(command_line));
// Ensure application init happens here
ApplicationAndroid::Get();
return reinterpret_cast<jlong>(nativeApp);
#endif // SB_IS(EVERGREEN_COMPATIBLE)
}

// StarboardBridge::GetInstance() should not be inlined in the
// header. This makes sure that when source files from multiple targets include
// this header they don't end up with different copies of the inlined code
Expand Down

0 comments on commit 632168a

Please sign in to comment.