195 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			195 lines
		
	
	
		
			7.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| /*
 | |
|  * Copyright (C) 2017 The Android Open Source Project
 | |
|  *
 | |
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | |
|  * you may not use this file except in compliance with the License.
 | |
|  * You may obtain a copy of the License at
 | |
|  *
 | |
|  *      http://www.apache.org/licenses/LICENSE-2.0
 | |
|  *
 | |
|  * Unless required by applicable law or agreed to in writing, software
 | |
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | |
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
|  * See the License for the specific language governing permissions and
 | |
|  * limitations under the License.
 | |
|  */
 | |
| 
 | |
| #include "base/file_utils.h"
 | |
| #include "class_loader_utils.h"
 | |
| #include "jni.h"
 | |
| #include "nativehelper/scoped_utf_chars.h"
 | |
| #include "oat_file_assistant.h"
 | |
| #include "oat_file_manager.h"
 | |
| #include "scoped_thread_state_change-inl.h"
 | |
| #include "thread.h"
 | |
| 
 | |
| namespace art {
 | |
| namespace Test692VdexInmemLoader {
 | |
| 
 | |
| extern "C" JNIEXPORT void JNICALL Java_Main_waitForVerifier(JNIEnv*, jclass) {
 | |
|   Runtime::Current()->GetOatFileManager().WaitForBackgroundVerificationTasks();
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT void JNICALL Java_Main_setProcessDataDir(JNIEnv* env, jclass, jstring jpath) {
 | |
|   const char* path = env->GetStringUTFChars(jpath, nullptr);
 | |
|   Runtime::Current()->SetProcessDataDirectory(path);
 | |
|   env->ReleaseStringUTFChars(jpath, path);
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesVerified(JNIEnv*,
 | |
|                                                                    jclass,
 | |
|                                                                    jobject loader) {
 | |
|   ScopedObjectAccess soa(Thread::Current());
 | |
|   StackHandleScope<2> hs(soa.Self());
 | |
|   Handle<mirror::ClassLoader> h_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));
 | |
| 
 | |
|   std::vector<const DexFile*> dex_files;
 | |
|   VisitClassLoaderDexFiles(
 | |
|       soa,
 | |
|       h_loader,
 | |
|       [&](const DexFile* dex_file) {
 | |
|         dex_files.push_back(dex_file);
 | |
|         return true;
 | |
|       });
 | |
| 
 | |
|   MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
 | |
|   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
 | |
| 
 | |
|   bool is_first = true;
 | |
|   bool all_verified = false;
 | |
|   for (const DexFile* dex_file : dex_files) {
 | |
|     for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) {
 | |
|       const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx));
 | |
|       h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader));
 | |
|       CHECK(h_class != nullptr) << "Could not find class " << desc;
 | |
|       bool is_verified = h_class->IsVerified();
 | |
|       if (is_first) {
 | |
|         all_verified = is_verified;
 | |
|         is_first = false;
 | |
|       } else if (all_verified != is_verified) {
 | |
|         // Classes should either all or none be verified.
 | |
|         LOG(ERROR) << "areClassesVerified is inconsistent";
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   return all_verified ? JNI_TRUE : JNI_FALSE;
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT bool JNICALL Java_Main_hasVdexFile(JNIEnv*,
 | |
|                                                         jclass,
 | |
|                                                         jobject loader) {
 | |
|   ScopedObjectAccess soa(Thread::Current());
 | |
|   StackHandleScope<1> hs(soa.Self());
 | |
|   Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));
 | |
| 
 | |
|   std::vector<const DexFile*> dex_files;
 | |
|   VisitClassLoaderDexFiles(
 | |
|       soa,
 | |
|       h_loader,
 | |
|       [&](const DexFile* dex_file) {
 | |
|         dex_files.push_back(dex_file);
 | |
|         return true;
 | |
|       });
 | |
| 
 | |
|   std::string dex_location = dex_files[0]->GetLocation();
 | |
|   std::string odex_filename;
 | |
|   std::string error_msg;
 | |
|   if (!OatFileAssistant::DexLocationToOdexFilename(dex_location,
 | |
|                                                    kRuntimeISA,
 | |
|                                                    &odex_filename,
 | |
|                                                    &error_msg)) {
 | |
|     LOG(WARNING) << "Could not get odex filename for " << dex_location << ": " << error_msg;
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   return OS::FileExists(GetVdexFilename(odex_filename).c_str());
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT jboolean JNICALL Java_Main_isBackedByOatFile(JNIEnv*,
 | |
|                                                                   jclass,
 | |
|                                                                   jobject loader) {
 | |
|   ScopedObjectAccess soa(Thread::Current());
 | |
|   StackHandleScope<1> hs(soa.Self());
 | |
|   Handle<mirror::ClassLoader> h_loader = hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader));
 | |
| 
 | |
|   bool is_first = true;
 | |
|   bool all_backed_by_oat = false;
 | |
| 
 | |
|   VisitClassLoaderDexFiles(
 | |
|       soa,
 | |
|       h_loader,
 | |
|       [&](const DexFile* dex_file) {
 | |
|         bool is_backed_by_oat = (dex_file->GetOatDexFile() != nullptr);
 | |
|         if (is_first) {
 | |
|           all_backed_by_oat = is_backed_by_oat;
 | |
|           is_first = false;
 | |
|         } else if (all_backed_by_oat != is_backed_by_oat) {
 | |
|           // DexFiles should either all or none be backed by oat.
 | |
|           LOG(ERROR) << "isBackedByOatFile is inconsistent";
 | |
|         }
 | |
|         return true;
 | |
|       });
 | |
|   return all_backed_by_oat ? JNI_TRUE : JNI_FALSE;
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT jboolean JNICALL Java_Main_areClassesPreverified(JNIEnv*,
 | |
|                                                                       jclass,
 | |
|                                                                       jobject loader) {
 | |
|   ScopedObjectAccess soa(Thread::Current());
 | |
|   StackHandleScope<2> hs(soa.Self());
 | |
|   Handle<mirror::ClassLoader> h_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader>(loader)));
 | |
| 
 | |
|   std::vector<const DexFile*> dex_files;
 | |
|   VisitClassLoaderDexFiles(
 | |
|       soa,
 | |
|       h_loader,
 | |
|       [&](const DexFile* dex_file) {
 | |
|         dex_files.push_back(dex_file);
 | |
|         return true;
 | |
|       });
 | |
| 
 | |
|   MutableHandle<mirror::Class> h_class(hs.NewHandle<mirror::Class>(nullptr));
 | |
|   ClassLinker* const class_linker = Runtime::Current()->GetClassLinker();
 | |
| 
 | |
|   bool is_first = true;
 | |
|   bool all_preverified = false;
 | |
|   for (const DexFile* dex_file : dex_files) {
 | |
|     for (uint16_t cdef_idx = 0; cdef_idx < dex_file->NumClassDefs(); ++cdef_idx) {
 | |
|       const char* desc = dex_file->GetClassDescriptor(dex_file->GetClassDef(cdef_idx));
 | |
|       h_class.Assign(class_linker->FindClass(soa.Self(), desc, h_loader));
 | |
|       CHECK(h_class != nullptr) << "Could not find class " << desc;
 | |
| 
 | |
|       ClassStatus oat_file_class_status(ClassStatus::kNotReady);
 | |
|       bool is_preverified = class_linker->VerifyClassUsingOatFile(
 | |
|           soa.Self(), *dex_file, h_class, oat_file_class_status);
 | |
| 
 | |
|       if (is_first) {
 | |
|         all_preverified = is_preverified;
 | |
|         is_first = false;
 | |
|       } else if (all_preverified != is_preverified) {
 | |
|         // Classes should either all or none be preverified.
 | |
|         LOG(ERROR) << "areClassesPreverified is inconsistent";
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return all_preverified ? JNI_TRUE : JNI_FALSE;
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT jint JNICALL Java_Main_getVdexCacheSize(JNIEnv*, jclass) {
 | |
|   return static_cast<jint>(OatFileManager::kAnonymousVdexCacheSize);
 | |
| }
 | |
| 
 | |
| extern "C" JNIEXPORT jboolean JNICALL Java_Main_isAnonymousVdexBasename(JNIEnv* env,
 | |
|                                                                         jclass,
 | |
|                                                                         jstring basename) {
 | |
|   if (basename == nullptr) {
 | |
|     return JNI_FALSE;
 | |
|   }
 | |
|   ScopedUtfChars basename_utf(env, basename);
 | |
|   return OatFileAssistant::IsAnonymousVdexBasename(basename_utf.c_str()) ? JNI_TRUE : JNI_FALSE;
 | |
| }
 | |
| 
 | |
| }  // namespace Test692VdexInmemLoader
 | |
| }  // namespace art
 |