1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "base/file_utils.h"
18 #include "class_loader_utils.h"
19 #include "jni.h"
20 #include "nativehelper/scoped_utf_chars.h"
21 #include "oat/oat_file_assistant.h"
22 #include "oat/oat_file_manager.h"
23 #include "scoped_thread_state_change-inl.h"
24 #include "thread.h"
25
26 namespace art {
27 namespace Test692VdexInmemLoader {
28
Java_Main_waitForVerifier(JNIEnv *,jclass)29 extern "C" JNIEXPORT void JNICALL Java_Main_waitForVerifier(JNIEnv*, jclass) {
30 Runtime::Current()->GetOatFileManager().WaitForBackgroundVerificationTasks();
31 }
32
Java_Main_setProcessDataDir(JNIEnv * env,jclass,jstring jpath)33 extern "C" JNIEXPORT void JNICALL Java_Main_setProcessDataDir(JNIEnv* env, jclass, jstring jpath) {
34 const char* path = env->GetStringUTFChars(jpath, nullptr);
35 Runtime::Current()->SetProcessDataDirectory(path);
36 env->ReleaseStringUTFChars(jpath, path);
37 }
38
Java_Main_areClassesVerified(JNIEnv *,jclass,jobject loader)39 extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesVerified(JNIEnv*,
40 jclass,
41 jobject loader) {
42 ScopedObjectAccess soa(Thread::Current());
43 StackHandleScope<2> hs(soa.Self());
44 Handle<mirror::ClassLoader> h_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));
45
46 std::vector<const DexFile*> dex_files;
47 VisitClassLoaderDexFiles(
48 soa.Self(),
49 h_loader,
50 [&](const DexFile* dex_file) {
51 dex_files.push_back(dex_file);
52 return true;
53 });
54
55 MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
56 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
57
58 bool is_first = true;
59 bool all_verified = false;
60 for (const DexFile* dex_file : dex_files) {
61 for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) {
62 const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx));
63 h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader));
64 CHECK(h_class != nullptr) << "Could not find class " << desc;
65 bool is_verified = h_class->IsVerified();
66 if (is_first) {
67 all_verified = is_verified;
68 is_first = false;
69 } else if (all_verified != is_verified) {
70 // Classes should either all or none be verified.
71 LOG(ERROR) << "areClassesVerified is inconsistent";
72 }
73 }
74 }
75 return all_verified ? JNI_TRUE : JNI_FALSE;
76 }
77
Java_Main_hasVdexFile(JNIEnv *,jclass,jobject loader)78 extern "C" JNIEXPORT bool JNICALL Java_Main_hasVdexFile(JNIEnv*,
79 jclass,
80 jobject loader) {
81 ScopedObjectAccess soa(Thread::Current());
82 StackHandleScope<1> hs(soa.Self());
83 Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));
84
85 std::vector<const DexFile*> dex_files;
86 VisitClassLoaderDexFiles(
87 soa.Self(),
88 h_loader,
89 [&](const DexFile* dex_file) {
90 dex_files.push_back(dex_file);
91 return true;
92 });
93
94 std::string dex_location = dex_files[0]->GetLocation();
95 std::string odex_filename;
96 std::string error_msg;
97 if (!OatFileAssistant::DexLocationToOdexFilename(dex_location,
98 kRuntimeISA,
99 &odex_filename,
100 &error_msg)) {
101 LOG(WARNING) << "Could not get odex filename for " << dex_location << ": " << error_msg;
102 return false;
103 }
104
105 return OS::FileExists(GetVdexFilename(odex_filename).c_str());
106 }
107
Java_Main_isBackedByOatFile(JNIEnv *,jclass,jobject loader)108 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isBackedByOatFile(JNIEnv*,
109 jclass,
110 jobject loader) {
111 ScopedObjectAccess soa(Thread::Current());
112 StackHandleScope<1> hs(soa.Self());
113 Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));
114
115 bool is_first = true;
116 bool all_backed_by_oat = false;
117
118 VisitClassLoaderDexFiles(
119 soa.Self(),
120 h_loader,
121 [&](const DexFile* dex_file) {
122 bool is_backed_by_oat = (dex_file->GetOatDexFile() != nullptr);
123 if (is_first) {
124 all_backed_by_oat = is_backed_by_oat;
125 is_first = false;
126 } else if (all_backed_by_oat != is_backed_by_oat) {
127 // DexFiles should either all or none be backed by oat.
128 LOG(ERROR) << "isBackedByOatFile is inconsistent";
129 }
130 return true;
131 });
132 return all_backed_by_oat ? JNI_TRUE : JNI_FALSE;
133 }
134
Java_Main_areClassesPreverified(JNIEnv *,jclass,jobject loader)135 extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesPreverified(JNIEnv*,
136 jclass,
137 jobject loader) {
138 ScopedObjectAccess soa(Thread::Current());
139 StackHandleScope<2> hs(soa.Self());
140 Handle<mirror::ClassLoader> h_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));
141
142 std::vector<const DexFile*> dex_files;
143 VisitClassLoaderDexFiles(
144 soa.Self(),
145 h_loader,
146 [&](const DexFile* dex_file) {
147 dex_files.push_back(dex_file);
148 return true;
149 });
150
151 MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
152 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
153
154 bool is_first = true;
155 bool all_preverified = false;
156 for (const DexFile* dex_file : dex_files) {
157 for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) {
158 const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx));
159 h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader));
160 CHECK(h_class != nullptr) << "Could not find class " << desc;
161
162 ClassStatus oat_file_class_status(ClassStatus::kNotReady);
163 bool is_preverified = class_linker->VerifyClassUsingOatFile(
164 soa.Self(), *dex_file, h_class, oat_file_class_status);
165
166 if (is_first) {
167 all_preverified = is_preverified;
168 is_first = false;
169 } else if (all_preverified != is_preverified) {
170 // Classes should either all or none be preverified.
171 LOG(ERROR) << "areClassesPreverified is inconsistent";
172 }
173 }
174 }
175
176 return all_preverified ? JNI_TRUE : JNI_FALSE;
177 }
178
Java_Main_getVdexCacheSize(JNIEnv *,jclass)179 extern "C" JNIEXPORT jint JNICALL Java_Main_getVdexCacheSize(JNIEnv*, jclass) {
180 return static_cast<jint>(OatFileManager::kAnonymousVdexCacheSize);
181 }
182
Java_Main_isAnonymousVdexBasename(JNIEnv * env,jclass,jstring basename)183 extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAnonymousVdexBasename(JNIEnv* env,
184 jclass,
185 jstring basename) {
186 if (basename == nullptr) {
187 return JNI_FALSE;
188 }
189 ScopedUtfChars basename_utf(env, basename);
190 return OatFileAssistant::IsAnonymousVdexBasename(basename_utf.c_str()) ? JNI_TRUE : JNI_FALSE;
191 }
192
193 } // namespace Test692VdexInmemLoader
194 } // namespace art
195