Commit ab42c0a8 authored by Joshua Peraza's avatar Joshua Peraza Committed by Commit Bot

android: build package paths using chrome's package

Monochrome uses /system/bin/app_process to load a Java class,
CrashpadMain, to start the Crashpad handler process. In order for
app_process to locate this class and for CrashpadMain to be able to
load the native libraries for Crashpad, CLASSPATH and LD_LIBRARY_PATH
need to be set with all the paths containing code that the Chrome
package depends on.

Add PackagePaths to build these paths.

This work is normally done internally by the Android framework:
https://cs.corp.google.com/android/frameworks/base/core/java/android/app/LoadedApk.java?rcl=7b2b4c838be94e6ca7cfbb255523c800da4a0cce&l=422

Bug: 912739
Change-Id: I30e4952fb17fea42bdc995296c47cf8a9f440866
Reviewed-on: https://chromium-review.googlesource.com/c/1366763Reviewed-by: default avatarRichard Coles <torne@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
Cr-Commit-Position: refs/heads/master@{#618363}
parent c1a8e417
...@@ -262,13 +262,4 @@ public abstract class PathUtils { ...@@ -262,13 +262,4 @@ public abstract class PathUtils {
public static String getExternalStorageDirectory() { public static String getExternalStorageDirectory() {
return Environment.getExternalStorageDirectory().getAbsolutePath(); return Environment.getExternalStorageDirectory().getAbsolutePath();
} }
/**
* @ return the path to the base apk.
*/
@SuppressWarnings("unused")
@CalledByNative
public static String getPathToBaseApk() {
return ContextUtils.getApplicationContext().getApplicationInfo().sourceDir;
}
} }
...@@ -78,14 +78,5 @@ bool GetExternalStorageDirectory(FilePath* result) { ...@@ -78,14 +78,5 @@ bool GetExternalStorageDirectory(FilePath* result) {
return true; return true;
} }
bool GetPathToBaseApk(FilePath* result) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jstring> path =
Java_PathUtils_getPathToBaseApk(env);
FilePath apk_path(ConvertJavaStringToUTF8(path));
*result = apk_path;
return true;
}
} // namespace android } // namespace android
} // namespace base } // namespace base
...@@ -49,10 +49,6 @@ BASE_EXPORT bool GetNativeLibraryDirectory(FilePath* result); ...@@ -49,10 +49,6 @@ BASE_EXPORT bool GetNativeLibraryDirectory(FilePath* result);
// is placed in the FilePath pointed to by 'result'. // is placed in the FilePath pointed to by 'result'.
BASE_EXPORT bool GetExternalStorageDirectory(FilePath* result); BASE_EXPORT bool GetExternalStorageDirectory(FilePath* result);
// Retrieves the absolute path the base APK. The result is placed in the
// FilePath pointed to by 'result'.
BASE_EXPORT bool GetPathToBaseApk(FilePath* result);
} // namespace android } // namespace android
} // namespace base } // namespace base
......
...@@ -7,6 +7,7 @@ import("//build/config/android/rules.gni") ...@@ -7,6 +7,7 @@ import("//build/config/android/rules.gni")
_jni_sources = [ _jni_sources = [
"java/src/org/chromium/components/crash/browser/ChildProcessCrashObserver.java", "java/src/org/chromium/components/crash/browser/ChildProcessCrashObserver.java",
"java/src/org/chromium/components/crash/browser/CrashDumpManager.java", "java/src/org/chromium/components/crash/browser/CrashDumpManager.java",
"java/src/org/chromium/components/crash/browser/PackagePaths.java",
"java/src/org/chromium/components/crash/CrashKeys.java", "java/src/org/chromium/components/crash/CrashKeys.java",
] ]
......
// Copyright 2018 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.
package org.chromium.components.crash.browser;
import android.annotation.SuppressLint;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Build;
import android.text.TextUtils;
import org.chromium.base.BuildInfo;
import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.CalledByNative;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* This class builds paths for the Chrome package.
*/
public abstract class PackagePaths {
private static final String TAG = "PackagePaths";
// Prevent instantiation.
private PackagePaths() {}
/**
* @ Build paths for the chrome/webview package for the purpose of loading CrashpadMain via
* /system/bin/app_process.
*/
@SuppressLint("NewApi")
@CalledByNative
public static String[] makePackagePaths(String arch) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {
return new String[] {"", ""};
}
try {
PackageManager pm = ContextUtils.getApplicationContext().getPackageManager();
PackageInfo pi = pm.getPackageInfo(
BuildInfo.getInstance().packageName, PackageManager.GET_SHARED_LIBRARY_FILES);
List<String> zipPaths = new ArrayList<>(10);
zipPaths.add(pi.applicationInfo.sourceDir);
if (pi.applicationInfo.splitSourceDirs != null) {
Collections.addAll(zipPaths, pi.applicationInfo.splitSourceDirs);
}
if (pi.applicationInfo.sharedLibraryFiles != null) {
Collections.addAll(zipPaths, pi.applicationInfo.sharedLibraryFiles);
}
List<String> libPaths = new ArrayList<>(10);
libPaths.add(pi.applicationInfo.nativeLibraryDir);
for (String zip : zipPaths) {
if (zip.endsWith(".apk")) {
libPaths.add(zip + "!/lib/" + arch);
}
}
libPaths.add(System.getProperty("java.library.path"));
return new String[] {TextUtils.join(File.pathSeparator, zipPaths),
TextUtils.join(File.pathSeparator, libPaths)};
} catch (NameNotFoundException e) {
throw new RuntimeException(e);
}
}
}
...@@ -66,6 +66,10 @@ static_library("app") { ...@@ -66,6 +66,10 @@ static_library("app") {
] ]
} }
if (is_android) {
deps += [ "//components/crash/android:jni_headers" ]
}
if (is_android || is_linux) { if (is_android || is_linux) {
deps += [ deps += [
"//base:base_static", "//base:base_static",
......
...@@ -5,6 +5,7 @@ include_rules = [ ...@@ -5,6 +5,7 @@ include_rules = [
"+components/gwp_asan/crash_handler/crash_handler.h", "+components/gwp_asan/crash_handler/crash_handler.h",
"+content/public/common/content_descriptors.h", "+content/public/common/content_descriptors.h",
"+content/public/common/result_codes.h", "+content/public/common/result_codes.h",
"+jni",
"+third_party/crashpad", "+third_party/crashpad",
"+third_party/lss/linux_syscall_support.h", "+third_party/lss/linux_syscall_support.h",
] ]
...@@ -40,7 +40,11 @@ ...@@ -40,7 +40,11 @@
#if defined(OS_ANDROID) #if defined(OS_ANDROID)
#include "base/android/build_info.h" #include "base/android/build_info.h"
#include "base/android/java_exception_reporter.h" #include "base/android/java_exception_reporter.h"
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/path_utils.h" #include "base/android/path_utils.h"
#include "jni/PackagePaths_jni.h"
#endif // OS_ANDROID #endif // OS_ANDROID
namespace crashpad { namespace crashpad {
...@@ -237,26 +241,42 @@ void SetBuildInfoAnnotations(std::map<std::string, std::string>* annotations) { ...@@ -237,26 +241,42 @@ void SetBuildInfoAnnotations(std::map<std::string, std::string>* annotations) {
#error "Unsupported target abi" #error "Unsupported target abi"
#endif #endif
void MakePackagePaths(std::string* classpath, std::string* libpath) {
JNIEnv* env = base::android::AttachCurrentThread();
base::android::ScopedJavaLocalRef<jstring> arch =
base::android::ConvertUTF8ToJavaString(env,
base::StringPiece(CURRENT_ABI));
base::android::ScopedJavaLocalRef<jobjectArray> paths =
Java_PackagePaths_makePackagePaths(env, arch);
base::android::ConvertJavaStringToUTF8(
env, static_cast<jstring>(env->GetObjectArrayElement(paths.obj(), 0)),
classpath);
base::android::ConvertJavaStringToUTF8(
env, static_cast<jstring>(env->GetObjectArrayElement(paths.obj(), 1)),
libpath);
}
// Copies and extends the current environment with CLASSPATH and LD_LIBRARY_PATH // Copies and extends the current environment with CLASSPATH and LD_LIBRARY_PATH
// set to library paths in the APK. // set to library paths in the APK.
bool BuildEnvironmentWithApk(std::vector<std::string>* result) { bool BuildEnvironmentWithApk(std::vector<std::string>* result) {
DCHECK(result->empty()); DCHECK(result->empty());
base::FilePath apk_path; std::string classpath;
if (!base::android::GetPathToBaseApk(&apk_path)) { std::string library_path;
return false; MakePackagePaths(&classpath, &library_path);
}
std::unique_ptr<base::Environment> env(base::Environment::Create()); std::unique_ptr<base::Environment> env(base::Environment::Create());
static constexpr char kClasspathVar[] = "CLASSPATH"; static constexpr char kClasspathVar[] = "CLASSPATH";
std::string classpath; std::string current_classpath;
env->GetVar(kClasspathVar, &classpath); env->GetVar(kClasspathVar, &current_classpath);
classpath = apk_path.value() + ":" + classpath; classpath += ":" + current_classpath;
static constexpr char kLdLibraryPathVar[] = "LD_LIBRARY_PATH"; static constexpr char kLdLibraryPathVar[] = "LD_LIBRARY_PATH";
std::string library_path; std::string current_library_path;
env->GetVar(kLdLibraryPathVar, &library_path); env->GetVar(kLdLibraryPathVar, &current_library_path);
library_path = apk_path.value() + "!/lib/" CURRENT_ABI ":" + library_path; library_path += ":" + current_library_path;
result->push_back("CLASSPATH=" + classpath); result->push_back("CLASSPATH=" + classpath);
result->push_back("LD_LIBRARY_PATH=" + library_path); result->push_back("LD_LIBRARY_PATH=" + library_path);
...@@ -415,6 +435,9 @@ class HandlerStarter { ...@@ -415,6 +435,9 @@ class HandlerStarter {
return database_path; return database_path;
} }
// TODO(jperaza): The logic for constructing an appropriate
// CLASSPATH/LD_LIBRARY_PATH won't work for Android Q+. The handler will
// need to be launched by executing the dynamic linker instead.
bool result = GetCrashpadClient().StartJavaHandlerAtCrash( bool result = GetCrashpadClient().StartJavaHandlerAtCrash(
kCrashpadJavaMain, &env, database_path, metrics_path, url, kCrashpadJavaMain, &env, database_path, metrics_path, url,
process_annotations, arguments); process_annotations, arguments);
...@@ -456,6 +479,9 @@ class HandlerStarter { ...@@ -456,6 +479,9 @@ class HandlerStarter {
return false; return false;
} }
// TODO(jperaza): The logic for constructing an appropriate
// CLASSPATH/LD_LIBRARY_PATH won't work for Android Q+. The handler will
// need to be launched by executing the dynamic linker instead.
bool result = GetCrashpadClient().StartJavaHandlerForClient( bool result = GetCrashpadClient().StartJavaHandlerForClient(
kCrashpadJavaMain, &env, database_path, metrics_path, url, kCrashpadJavaMain, &env, database_path, metrics_path, url,
process_annotations, arguments, fd); process_annotations, arguments, fd);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment