1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/android/library_loader/library_loader_hooks.h"
7 #include "base/android/command_line_android.h"
8 #include "base/android/jni_string.h"
9 #include "base/android/library_loader/library_load_from_apk_status_codes.h"
10 #include "base/android/library_loader/library_prefetcher.h"
11 #include "base/at_exit.h"
12 #include "base/metrics/histogram.h"
13 #include "jni/LibraryLoader_jni.h"
20 base::AtExitManager
* g_at_exit_manager
= NULL
;
21 const char* g_library_version_number
= "";
22 LibraryLoadedHook
* g_registration_callback
= NULL
;
24 enum RendererHistogramCode
{
25 // Renderer load at fixed address success, fail, or not attempted.
26 // Renderers do not attempt to load at at fixed address if on a
27 // low-memory device on which browser load at fixed address has already
31 LFA_NOT_ATTEMPTED
= 2,
33 // End sentinel, also used as nothing-pending indicator.
34 MAX_RENDERER_HISTOGRAM_CODE
= 3,
35 NO_PENDING_HISTOGRAM_CODE
= MAX_RENDERER_HISTOGRAM_CODE
38 enum BrowserHistogramCode
{
39 // Non-low-memory random address browser loads.
40 NORMAL_LRA_SUCCESS
= 0,
42 // Low-memory browser loads at fixed address, success or fail.
43 LOW_MEMORY_LFA_SUCCESS
= 1,
44 LOW_MEMORY_LFA_BACKOFF_USED
= 2,
46 MAX_BROWSER_HISTOGRAM_CODE
= 3,
49 RendererHistogramCode g_renderer_histogram_code
= NO_PENDING_HISTOGRAM_CODE
;
51 // The amount of time, in milliseconds, that it took to load the shared
52 // libraries in the renderer. Set in
53 // RegisterChromiumAndroidLinkerRendererHistogram.
54 long g_renderer_library_load_time_ms
= 0;
58 static void RegisterChromiumAndroidLinkerRendererHistogram(
60 const JavaParamRef
<jobject
>& jcaller
,
61 jboolean requested_shared_relro
,
62 jboolean load_at_fixed_address_failed
,
63 jlong library_load_time_ms
) {
64 // Note a pending histogram value for later recording.
65 if (requested_shared_relro
) {
66 g_renderer_histogram_code
= load_at_fixed_address_failed
67 ? LFA_BACKOFF_USED
: LFA_SUCCESS
;
69 g_renderer_histogram_code
= LFA_NOT_ATTEMPTED
;
72 g_renderer_library_load_time_ms
= library_load_time_ms
;
75 void RecordChromiumAndroidLinkerRendererHistogram() {
76 if (g_renderer_histogram_code
== NO_PENDING_HISTOGRAM_CODE
)
78 // Record and release the pending histogram value.
79 UMA_HISTOGRAM_ENUMERATION("ChromiumAndroidLinker.RendererStates",
80 g_renderer_histogram_code
,
81 MAX_RENDERER_HISTOGRAM_CODE
);
82 g_renderer_histogram_code
= NO_PENDING_HISTOGRAM_CODE
;
84 // Record how long it took to load the shared libraries.
85 UMA_HISTOGRAM_TIMES("ChromiumAndroidLinker.RendererLoadTime",
86 base::TimeDelta::FromMilliseconds(g_renderer_library_load_time_ms
));
89 static void RecordChromiumAndroidLinkerBrowserHistogram(
91 const JavaParamRef
<jobject
>& jcaller
,
92 jboolean is_using_browser_shared_relros
,
93 jboolean load_at_fixed_address_failed
,
94 jint library_load_from_apk_status
,
95 jlong library_load_time_ms
) {
96 // For low-memory devices, record whether or not we successfully loaded the
97 // browser at a fixed address. Otherwise just record a normal invocation.
98 BrowserHistogramCode histogram_code
;
99 if (is_using_browser_shared_relros
) {
100 histogram_code
= load_at_fixed_address_failed
101 ? LOW_MEMORY_LFA_BACKOFF_USED
: LOW_MEMORY_LFA_SUCCESS
;
103 histogram_code
= NORMAL_LRA_SUCCESS
;
105 UMA_HISTOGRAM_ENUMERATION("ChromiumAndroidLinker.BrowserStates",
107 MAX_BROWSER_HISTOGRAM_CODE
);
109 // Record the device support for loading a library directly from the APK file.
110 UMA_HISTOGRAM_ENUMERATION("ChromiumAndroidLinker.LibraryLoadFromApkStatus",
111 library_load_from_apk_status
,
112 LIBRARY_LOAD_FROM_APK_STATUS_CODES_MAX
);
114 // Record how long it took to load the shared libraries.
115 UMA_HISTOGRAM_TIMES("ChromiumAndroidLinker.BrowserLoadTime",
116 base::TimeDelta::FromMilliseconds(library_load_time_ms
));
119 void SetLibraryLoadedHook(LibraryLoadedHook
* func
) {
120 g_registration_callback
= func
;
123 static void InitCommandLine(
125 const JavaParamRef
<jobject
>& jcaller
,
126 const JavaParamRef
<jobjectArray
>& init_command_line
) {
127 InitNativeCommandLineFromJavaArray(env
, init_command_line
);
130 static jboolean
LibraryLoaded(JNIEnv
* env
,
131 const JavaParamRef
<jobject
>& jcaller
) {
132 if (g_registration_callback
== NULL
) {
135 return g_registration_callback(env
, NULL
);
138 void LibraryLoaderExitHook() {
139 if (g_at_exit_manager
) {
140 delete g_at_exit_manager
;
141 g_at_exit_manager
= NULL
;
145 static jboolean
ForkAndPrefetchNativeLibrary(
147 const JavaParamRef
<jclass
>& clazz
) {
148 return NativeLibraryPrefetcher::ForkAndPrefetchNativeLibrary();
151 bool RegisterLibraryLoaderEntryHook(JNIEnv
* env
) {
152 return RegisterNativesImpl(env
);
155 void SetVersionNumber(const char* version_number
) {
156 g_library_version_number
= strdup(version_number
);
159 ScopedJavaLocalRef
<jstring
> GetVersionNumber(
161 const JavaParamRef
<jobject
>& jcaller
) {
162 return ConvertUTF8ToJavaString(env
, g_library_version_number
);
165 LibraryProcessType
GetLibraryProcessType(JNIEnv
* env
) {
166 return static_cast<LibraryProcessType
>(
167 Java_LibraryLoader_getLibraryProcessType(env
));
170 void InitAtExitManager() {
171 g_at_exit_manager
= new base::AtExitManager();
174 } // namespace android