Skip to content

Commit

Permalink
Adopt for Android R
Browse files Browse the repository at this point in the history
Signed-off-by: tiann <twsxtd@gmail.com>
  • Loading branch information
tiann committed Jul 13, 2020
1 parent c995ef1 commit 1a660a9
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 21 deletions.
4 changes: 2 additions & 2 deletions library/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
/*

externalNativeBuild {
cmake {
path "src/main/cpp/CMakeLists.txt"
}
}*/
}
lintOptions {
abortOnError false
}
Expand Down
60 changes: 45 additions & 15 deletions library/src/main/cpp/art.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <android/log.h>
#include <vector>
#include <string>
#include <stdlib.h>
#include <sys/system_properties.h>

#define LOGV(...) ((void)__android_log_print(ANDROID_LOG_INFO, "FreeReflect", __VA_ARGS__))

Expand All @@ -26,8 +28,36 @@ int findOffset(void *start, int regionStart, int regionEnd, T value) {
return -2;
}

template<typename Runtime>
int unseal0(Runtime *partialRuntime) {
bool is_java_debuggable = partialRuntime->is_java_debuggable_;
bool is_native_debuggable = partialRuntime->is_native_debuggable_;
bool safe_mode = partialRuntime->safe_mode_;

// TODO validate

LOGV("is_java_debuggable: %d, is_native_debuggable: %d, safe_mode: %d", is_java_debuggable,
is_native_debuggable, safe_mode);
LOGV("hidden api policy before : %d", partialRuntime->hidden_api_policy_);
LOGV("fingerprint: %s", partialRuntime->fingerprint_.c_str());

partialRuntime->hidden_api_policy_ = EnforcementPolicy::kNoChecks;
LOGV("hidden api policy after: %d", partialRuntime->hidden_api_policy_);
return 0;
}

int unseal(JNIEnv *env, jint targetSdkVersion) {

char api_level_str[5];
char preview_api_str[5];
__system_property_get("ro.build.version.sdk", api_level_str);
__system_property_get("ro.build.version.preview_sdk", preview_api_str);

int api_level = atoi(api_level_str);
bool is_preview = atoi(preview_api_str) > 0;

bool isAndroidR = api_level >= 30 || (api_level == 29 && is_preview);

JavaVM *javaVM;
env->GetJavaVM(&javaVM);

Expand All @@ -44,7 +74,12 @@ int unseal(JNIEnv *env, jint targetSdkVersion) {
return -1;
}

int targetSdkVersionOffset = findOffset(runtime, offsetOfVmExt, MAX, targetSdkVersion);
int startOffset = offsetOfVmExt;
if (isAndroidR) {
startOffset += 200;
}

int targetSdkVersionOffset = findOffset(runtime, startOffset, MAX, targetSdkVersion);
LOGV("target: %d", targetSdkVersionOffset);

if (targetSdkVersionOffset < 0) {
Expand Down Expand Up @@ -83,21 +118,16 @@ int unseal(JNIEnv *env, jint targetSdkVersion) {
}
*/

PartialRuntime *partialRuntime = (PartialRuntime *) ((char *) runtime + targetSdkVersionOffset);

bool is_java_debuggable = partialRuntime->is_java_debuggable_;
bool is_native_debuggable = partialRuntime->is_native_debuggable_;
bool safe_mode = partialRuntime->safe_mode_;

// TODO validate

LOGV("is_java_debuggable: %d, is_native_debuggable: %d, safe_mode: %d", is_java_debuggable, is_native_debuggable, safe_mode);
LOGV("hidden api policy before : %d", partialRuntime->hidden_api_policy_);
LOGV("fingerprint: %s", partialRuntime->fingerprint_.c_str());

partialRuntime->hidden_api_policy_ = EnforcementPolicy::kNoChecks;
if (isAndroidR) {
auto *partialRuntime = reinterpret_cast<PartialRuntimeR *>((char *) runtime +
targetSdkVersionOffset);
unseal0<PartialRuntimeR>(partialRuntime);
} else {
auto *partialRuntime = (PartialRuntime *) ((char *) runtime +
targetSdkVersionOffset);
unseal0<PartialRuntime>(partialRuntime);
}

LOGV("hidden api policy after: %d", partialRuntime->hidden_api_policy_);
return 0;
}

88 changes: 84 additions & 4 deletions library/src/main/cpp/art.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ struct ExperimentalFlags {
// This must be kept in sync with ApplicationInfo.ApiEnforcementPolicy in
// frameworks/base/core/java/android/content/pm/ApplicationInfo.java
enum class EnforcementPolicy {
kNoChecks = 0,
kJustWarn = 1, // keep checks enabled, but allow everything (enables logging)
kNoChecks = 0,
kJustWarn = 1, // keep checks enabled, but allow everything (enables logging)
kDarkGreyAndBlackList = 2, // ban dark grey & blacklist
kBlacklistOnly = 3, // ban blacklist violations only
kBlacklistOnly = 3, // ban blacklist violations only
kMax = 3,
};

Expand Down Expand Up @@ -73,7 +73,7 @@ struct PartialRuntime {
std::string fingerprint_;
// Oat file manager, keeps track of what oat files are open.
// OatFileManager* oat_file_manager_;
void* oat_file_manager_;
void *oat_file_manager_;
// Whether or not we are on a low RAM device.
bool is_low_memory_mode_;
// Whether or not we use MADV_RANDOM on files that are thought to have random access patterns.
Expand All @@ -85,6 +85,86 @@ struct PartialRuntime {
EnforcementPolicy hidden_api_policy_;
};

// Android R DP2: https://cs.android.com/android/platform/superproject/+/master:art/runtime/runtime.h;l=1179?q=runtime.h&ss=android%2Fplatform%2Fsuperproject
struct PartialRuntimeR {
// Specifies target SDK version to allow workarounds for certain API levels.
uint32_t target_sdk_version_;

// A set of disabled compat changes for the running app, all other changes are enabled.
// std::set<uint64_t> disabled_compat_changes_;
void *disabled_compat_changes_[3];

// Implicit checks flags.
bool implicit_null_checks_; // NullPointer checks are implicit.
bool implicit_so_checks_; // StackOverflow checks are implicit.
bool implicit_suspend_checks_; // Thread suspension checks are implicit.

// Whether or not the sig chain (and implicitly the fault handler) should be
// disabled. Tools like dex2oat don't need them. This enables
// building a statically link version of dex2oat.
bool no_sig_chain_;

// Force the use of native bridge even if the app ISA matches the runtime ISA.
bool force_native_bridge_;

// Whether or not a native bridge has been loaded.
//
// The native bridge allows running native code compiled for a foreign ISA. The way it works is,
// if standard dlopen fails to load native library associated with native activity, it calls to
// the native bridge to load it and then gets the trampoline for the entry to native activity.
//
// The option 'native_bridge_library_filename' specifies the name of the native bridge.
// When non-empty the native bridge will be loaded from the given file. An empty value means
// that there's no native bridge.
bool is_native_bridge_loaded_;

// Whether we are running under native debugger.
bool is_native_debuggable_;

// whether or not any async exceptions have ever been thrown. This is used to speed up the
// MterpShouldSwitchInterpreters function.
bool async_exceptions_thrown_;

// Whether anything is going to be using the shadow-frame APIs to force a function to return
// early. Doing this requires that (1) we be debuggable and (2) that mterp is exited.
bool non_standard_exits_enabled_;

// Whether Java code needs to be debuggable.
bool is_java_debuggable_;

bool is_profileable_from_shell_ = false;

// The maximum number of failed boots we allow before pruning the dalvik cache
// and trying again. This option is only inspected when we're running as a
// zygote.
uint32_t zygote_max_failed_boots_;

// Enable experimental opcodes that aren't fully specified yet. The intent is to
// eventually publish them as public-usable opcodes, but they aren't ready yet.
//
// Experimental opcodes should not be used by other production code.
ExperimentalFlags experimental_flags_;

// Contains the build fingerprint, if given as a parameter.
std::string fingerprint_;

// Oat file manager, keeps track of what oat files are open.
void *oat_file_manager_;

// Whether or not we are on a low RAM device.
bool is_low_memory_mode_;

// Whether or not we use MADV_RANDOM on files that are thought to have random access patterns.
// This is beneficial for low RAM devices since it reduces page cache thrashing.
bool madvise_random_access_;

// Whether the application should run in safe mode, that is, interpreter only.
bool safe_mode_;

// Whether access checks on hidden API should be performed.
EnforcementPolicy hidden_api_policy_;
};


int unseal(JNIEnv *env, jint targetSdkVersion);

Expand Down

0 comments on commit 1a660a9

Please sign in to comment.