mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 22:36:09 +03:00
255 lines
8.3 KiB
C++
255 lines
8.3 KiB
C++
|
// Copyright 2014 The Chromium 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 "base/android/library_loader/library_loader_hooks.h"
|
||
|
|
||
|
#include "base/android/jni_string.h"
|
||
|
#include "base/android/library_loader/anchor_functions_buildflags.h"
|
||
|
#include "base/android/library_loader/library_load_from_apk_status_codes.h"
|
||
|
#include "base/android/library_loader/library_prefetcher.h"
|
||
|
#include "base/android/orderfile/orderfile_buildflags.h"
|
||
|
#include "base/at_exit.h"
|
||
|
#include "base/base_switches.h"
|
||
|
#include "base/command_line.h"
|
||
|
#include "base/metrics/histogram.h"
|
||
|
#include "base/metrics/histogram_functions.h"
|
||
|
#include "base/metrics/histogram_macros.h"
|
||
|
#include "jni/LibraryLoader_jni.h"
|
||
|
|
||
|
#if BUILDFLAG(ORDERFILE_INSTRUMENTATION)
|
||
|
#include "base/android/orderfile/orderfile_instrumentation.h"
|
||
|
#endif
|
||
|
|
||
|
namespace base {
|
||
|
namespace android {
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
base::AtExitManager* g_at_exit_manager = NULL;
|
||
|
const char* g_library_version_number = "";
|
||
|
LibraryLoadedHook* g_registration_callback = NULL;
|
||
|
NativeInitializationHook* g_native_initialization_hook = NULL;
|
||
|
|
||
|
enum RendererHistogramCode {
|
||
|
// Renderer load at fixed address success, fail, or not attempted.
|
||
|
// Renderers do not attempt to load at at fixed address if on a
|
||
|
// low-memory device on which browser load at fixed address has already
|
||
|
// failed.
|
||
|
LFA_SUCCESS = 0,
|
||
|
LFA_BACKOFF_USED = 1,
|
||
|
LFA_NOT_ATTEMPTED = 2,
|
||
|
|
||
|
// End sentinel, also used as nothing-pending indicator.
|
||
|
MAX_RENDERER_HISTOGRAM_CODE = 3,
|
||
|
NO_PENDING_HISTOGRAM_CODE = MAX_RENDERER_HISTOGRAM_CODE
|
||
|
};
|
||
|
|
||
|
enum BrowserHistogramCode {
|
||
|
// Non-low-memory random address browser loads.
|
||
|
NORMAL_LRA_SUCCESS = 0,
|
||
|
|
||
|
// Low-memory browser loads at fixed address, success or fail.
|
||
|
LOW_MEMORY_LFA_SUCCESS = 1,
|
||
|
LOW_MEMORY_LFA_BACKOFF_USED = 2,
|
||
|
|
||
|
MAX_BROWSER_HISTOGRAM_CODE = 3,
|
||
|
};
|
||
|
|
||
|
RendererHistogramCode g_renderer_histogram_code = NO_PENDING_HISTOGRAM_CODE;
|
||
|
|
||
|
// Indicate whether g_library_preloader_renderer_histogram_code is valid
|
||
|
bool g_library_preloader_renderer_histogram_code_registered = false;
|
||
|
|
||
|
// The return value of NativeLibraryPreloader.loadLibrary() in child processes,
|
||
|
// it is initialized to the invalid value which shouldn't showup in UMA report.
|
||
|
int g_library_preloader_renderer_histogram_code = -1;
|
||
|
|
||
|
// The amount of time, in milliseconds, that it took to load the shared
|
||
|
// libraries in the renderer. Set in
|
||
|
// RegisterChromiumAndroidLinkerRendererHistogram.
|
||
|
long g_renderer_library_load_time_ms = 0;
|
||
|
|
||
|
void RecordChromiumAndroidLinkerRendererHistogram() {
|
||
|
if (g_renderer_histogram_code == NO_PENDING_HISTOGRAM_CODE)
|
||
|
return;
|
||
|
// Record and release the pending histogram value.
|
||
|
UMA_HISTOGRAM_ENUMERATION("ChromiumAndroidLinker.RendererStates",
|
||
|
g_renderer_histogram_code,
|
||
|
MAX_RENDERER_HISTOGRAM_CODE);
|
||
|
g_renderer_histogram_code = NO_PENDING_HISTOGRAM_CODE;
|
||
|
|
||
|
// Record how long it took to load the shared libraries.
|
||
|
UMA_HISTOGRAM_TIMES("ChromiumAndroidLinker.RendererLoadTime",
|
||
|
base::TimeDelta::FromMilliseconds(g_renderer_library_load_time_ms));
|
||
|
}
|
||
|
|
||
|
void RecordLibraryPreloaderRendereHistogram() {
|
||
|
if (g_library_preloader_renderer_histogram_code_registered) {
|
||
|
UmaHistogramSparse("Android.NativeLibraryPreloader.Result.Renderer",
|
||
|
g_library_preloader_renderer_histogram_code);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
|
||
|
bool ShouldDoOrderfileMemoryOptimization() {
|
||
|
return CommandLine::ForCurrentProcess()->HasSwitch(
|
||
|
switches::kOrderfileMemoryOptimization);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
static void JNI_LibraryLoader_RegisterChromiumAndroidLinkerRendererHistogram(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jobject>& jcaller,
|
||
|
jboolean requested_shared_relro,
|
||
|
jboolean load_at_fixed_address_failed,
|
||
|
jlong library_load_time_ms) {
|
||
|
// Note a pending histogram value for later recording.
|
||
|
if (requested_shared_relro) {
|
||
|
g_renderer_histogram_code = load_at_fixed_address_failed
|
||
|
? LFA_BACKOFF_USED : LFA_SUCCESS;
|
||
|
} else {
|
||
|
g_renderer_histogram_code = LFA_NOT_ATTEMPTED;
|
||
|
}
|
||
|
|
||
|
g_renderer_library_load_time_ms = library_load_time_ms;
|
||
|
}
|
||
|
|
||
|
static void JNI_LibraryLoader_RecordChromiumAndroidLinkerBrowserHistogram(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jobject>& jcaller,
|
||
|
jboolean is_using_browser_shared_relros,
|
||
|
jboolean load_at_fixed_address_failed,
|
||
|
jint library_load_from_apk_status,
|
||
|
jlong library_load_time_ms) {
|
||
|
// For low-memory devices, record whether or not we successfully loaded the
|
||
|
// browser at a fixed address. Otherwise just record a normal invocation.
|
||
|
BrowserHistogramCode histogram_code;
|
||
|
if (is_using_browser_shared_relros) {
|
||
|
histogram_code = load_at_fixed_address_failed
|
||
|
? LOW_MEMORY_LFA_BACKOFF_USED : LOW_MEMORY_LFA_SUCCESS;
|
||
|
} else {
|
||
|
histogram_code = NORMAL_LRA_SUCCESS;
|
||
|
}
|
||
|
UMA_HISTOGRAM_ENUMERATION("ChromiumAndroidLinker.BrowserStates",
|
||
|
histogram_code,
|
||
|
MAX_BROWSER_HISTOGRAM_CODE);
|
||
|
|
||
|
// Record the device support for loading a library directly from the APK file.
|
||
|
UMA_HISTOGRAM_ENUMERATION(
|
||
|
"ChromiumAndroidLinker.LibraryLoadFromApkStatus",
|
||
|
static_cast<LibraryLoadFromApkStatusCodes>(library_load_from_apk_status),
|
||
|
LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX);
|
||
|
|
||
|
// Record how long it took to load the shared libraries.
|
||
|
UMA_HISTOGRAM_TIMES("ChromiumAndroidLinker.BrowserLoadTime",
|
||
|
base::TimeDelta::FromMilliseconds(library_load_time_ms));
|
||
|
}
|
||
|
|
||
|
static void JNI_LibraryLoader_RecordLibraryPreloaderBrowserHistogram(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jobject>& jcaller,
|
||
|
jint status) {
|
||
|
UmaHistogramSparse("Android.NativeLibraryPreloader.Result.Browser", status);
|
||
|
}
|
||
|
|
||
|
static void JNI_LibraryLoader_RegisterLibraryPreloaderRendererHistogram(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jobject>& jcaller,
|
||
|
jint status) {
|
||
|
g_library_preloader_renderer_histogram_code = status;
|
||
|
g_library_preloader_renderer_histogram_code_registered = true;
|
||
|
}
|
||
|
|
||
|
void SetNativeInitializationHook(
|
||
|
NativeInitializationHook native_initialization_hook) {
|
||
|
g_native_initialization_hook = native_initialization_hook;
|
||
|
}
|
||
|
|
||
|
void RecordLibraryLoaderRendererHistograms() {
|
||
|
RecordChromiumAndroidLinkerRendererHistogram();
|
||
|
RecordLibraryPreloaderRendereHistogram();
|
||
|
}
|
||
|
|
||
|
void SetLibraryLoadedHook(LibraryLoadedHook* func) {
|
||
|
g_registration_callback = func;
|
||
|
}
|
||
|
|
||
|
static jboolean JNI_LibraryLoader_LibraryLoaded(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jobject>& jcaller,
|
||
|
jint library_process_type) {
|
||
|
#if BUILDFLAG(ORDERFILE_INSTRUMENTATION)
|
||
|
orderfile::StartDelayedDump();
|
||
|
#endif
|
||
|
|
||
|
#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
|
||
|
if (ShouldDoOrderfileMemoryOptimization()) {
|
||
|
NativeLibraryPrefetcher::MadviseForOrderfile();
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
if (g_native_initialization_hook &&
|
||
|
!g_native_initialization_hook(
|
||
|
static_cast<LibraryProcessType>(library_process_type)))
|
||
|
return false;
|
||
|
if (g_registration_callback && !g_registration_callback(env, nullptr))
|
||
|
return false;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void LibraryLoaderExitHook() {
|
||
|
if (g_at_exit_manager) {
|
||
|
delete g_at_exit_manager;
|
||
|
g_at_exit_manager = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void JNI_LibraryLoader_ForkAndPrefetchNativeLibrary(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz) {
|
||
|
#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
|
||
|
return NativeLibraryPrefetcher::ForkAndPrefetchNativeLibrary(
|
||
|
ShouldDoOrderfileMemoryOptimization());
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static jint JNI_LibraryLoader_PercentageOfResidentNativeLibraryCode(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz) {
|
||
|
#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
|
||
|
return NativeLibraryPrefetcher::PercentageOfResidentNativeLibraryCode();
|
||
|
#else
|
||
|
return -1;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
static void JNI_LibraryLoader_PeriodicallyCollectResidency(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jclass>& clazz) {
|
||
|
#if BUILDFLAG(SUPPORTS_CODE_ORDERING)
|
||
|
NativeLibraryPrefetcher::PeriodicallyCollectResidency();
|
||
|
#else
|
||
|
LOG(WARNING) << "Collecting residency is not supported.";
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void SetVersionNumber(const char* version_number) {
|
||
|
g_library_version_number = strdup(version_number);
|
||
|
}
|
||
|
|
||
|
ScopedJavaLocalRef<jstring> JNI_LibraryLoader_GetVersionNumber(
|
||
|
JNIEnv* env,
|
||
|
const JavaParamRef<jobject>& jcaller) {
|
||
|
return ConvertUTF8ToJavaString(env, g_library_version_number);
|
||
|
}
|
||
|
|
||
|
void InitAtExitManager() {
|
||
|
g_at_exit_manager = new base::AtExitManager();
|
||
|
}
|
||
|
|
||
|
} // namespace android
|
||
|
} // namespace base
|