#include "base/threading/platform_thread.h"
#include <errno.h>
#include <pthread.h>
#include <stddef.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <optional>
#include "base/android/android_info.h"
#include "base/android/jni_android.h"
#include "base/feature_list.h"
#include "base/logging.h"
#include "base/system/sys_info.h"
#include "base/threading/platform_thread_internal_posix.h"
#include "base/threading/thread_id_name_manager.h"
#include "base/tasks_jni/ThreadUtils_jni.h"
namespace base {
BASE_FEATURE(kIncreaseDisplayCriticalThreadPriority,
"RaiseDisplayCriticalThreadPriority",
base::FEATURE_DISABLED_BY_DEFAULT);
namespace internal {
static bool ShouldBoostDisplayCriticalThreadPriority() {
static bool is_google_soc = SysInfo::SocManufacturer() == "Google";
return !is_google_soc &&
base::FeatureList::IsEnabled(kIncreaseDisplayCriticalThreadPriority);
}
const ThreadTypeToNiceValuePairForTest kThreadTypeToNiceValueMapForTest[7] = {
{ThreadType::kRealtimeAudio, -16}, {ThreadType::kDisplayCritical, -4},
{ThreadType::kDefault, 0}, {ThreadType::kUtility, 1},
{ThreadType::kBackground, 10},
};
int ThreadTypeToNiceValue(const ThreadType thread_type) {
switch (thread_type) {
case ThreadType::kBackground:
return 10;
case ThreadType::kUtility:
return 1;
case ThreadType::kDefault:
return 0;
case ThreadType::kDisplayCritical:
case ThreadType::kInteractive:
if (ShouldBoostDisplayCriticalThreadPriority()) {
return -12;
}
return -4;
case ThreadType::kRealtimeAudio:
return -16;
}
}
bool CanSetThreadTypeToRealtimeAudio() {
return true;
}
void SetCurrentThreadTypeImpl(ThreadType thread_type,
MessagePumpType pump_type_hint) {
if (thread_type == ThreadType::kRealtimeAudio &&
base::android::android_info::sdk_int() <
base::android::android_info::SDK_VERSION_T) {
JNIEnv* env = base::android::AttachCurrentThread();
Java_ThreadUtils_setThreadPriorityAudio(env,
PlatformThread::CurrentId().raw());
return;
}
if (thread_type == ThreadType::kDisplayCritical &&
pump_type_hint == MessagePumpType::UI &&
GetCurrentThreadNiceValue() <=
ThreadTypeToNiceValue(ThreadType::kDisplayCritical)) {
return;
}
SetThreadNiceFromType(PlatformThread::CurrentId(), thread_type);
}
std::optional<ThreadType> GetCurrentEffectiveThreadTypeForPlatformForTest() {
JNIEnv* env = base::android::AttachCurrentThread();
if (Java_ThreadUtils_isThreadPriorityAudio(
env, PlatformThread::CurrentId().raw())) {
return std::make_optional(ThreadType::kRealtimeAudio);
}
return std::nullopt;
}
PlatformPriorityOverride SetThreadTypeOverride(
PlatformThreadHandle thread_handle,
ThreadType thread_type) {
PlatformThreadId thread_id(
pthread_gettid_np(thread_handle.platform_handle()));
if (GetThreadNiceValue(thread_id) <= ThreadTypeToNiceValue(thread_type)) {
return false;
}
return SetThreadNiceFromType(thread_id, thread_type);
}
void RemoveThreadTypeOverrideImpl(
const PlatformPriorityOverride& priority_override_handle,
ThreadType thread_type) {
if (!priority_override_handle) {
return;
}
SetCurrentThreadTypeImpl(thread_type, MessagePumpType::DEFAULT);
}
}
void PlatformThread::SetName(const std::string& name) {
SetNameCommon(name);
if (PlatformThread::CurrentId().raw() == getpid()) {
return;
}
int err = prctl(PR_SET_NAME, name.c_str());
if (err < 0 && errno != EPERM) {
DPLOG(ERROR) << "prctl(PR_SET_NAME)";
}
}
void InitThreading() {}
void TerminateOnThread() {
base::android::DetachFromVM();
}
size_t GetDefaultThreadStackSize(const pthread_attr_t& attributes) {
#if !defined(ADDRESS_SANITIZER)
return 0;
#else
return 2 * (1 << 20);
#endif
}
}
DEFINE_JNI(ThreadUtils)