/* * Copyright 2019 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 "tuningfork_utils.h" #include <sys/stat.h> #include <errno.h> #define LOG_TAG "TuningFork" #include "Log.h" #include <android/asset_manager.h> #include <android/asset_manager_jni.h> namespace tuningfork { namespace apk_utils { // Get an asset from this APK's asset directory. // Returns NULL if the asset could not be found. // Asset_close must be called once the asset is no longer needed. AAsset* GetAsset(JNIEnv* env, jobject activity, const char* name) { jclass cls = env->FindClass("android/content/Context"); jmethodID get_assets = env->GetMethodID(cls, "getAssets", "()Landroid/content/res/AssetManager;"); if(get_assets==nullptr) { ALOGE("No Context.getAssets() method"); return nullptr; } auto javaMgr = env->CallObjectMethod(activity, get_assets); if (javaMgr == nullptr) { ALOGE("No java asset manager"); return nullptr; } AAssetManager* mgr = AAssetManager_fromJava(env, javaMgr); if (mgr == nullptr) { ALOGE("No asset manager"); return nullptr; } AAsset* asset = AAssetManager_open(mgr, name, AASSET_MODE_BUFFER); if (asset == nullptr) { ALOGW("Can't find %s in APK", name); return nullptr; } return asset; } // Get the app's version code. Also fills packageNameStr with the package name // if it is non-null. int GetVersionCode(JNIEnv *env, jobject context, std::string* packageNameStr) { jstring packageName; jobject packageManagerObj; jobject packageInfoObj; jclass contextClass = env->GetObjectClass( context); jmethodID getPackageNameMid = env->GetMethodID( contextClass, "getPackageName", "()Ljava/lang/String;"); jmethodID getPackageManager = env->GetMethodID( contextClass, "getPackageManager", "()Landroid/content/pm/PackageManager;"); jclass packageManagerClass = env->FindClass("android/content/pm/PackageManager"); jmethodID getPackageInfo = env->GetMethodID( packageManagerClass, "getPackageInfo", "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); jclass packageInfoClass = env->FindClass("android/content/pm/PackageInfo"); jfieldID versionCodeFid = env->GetFieldID( packageInfoClass, "versionCode", "I"); packageName = (jstring)env->CallObjectMethod(context, getPackageNameMid); if (packageNameStr != nullptr) { // Fill packageNameStr with the package name const char* packageName_cstr = env->GetStringUTFChars(packageName, NULL); *packageNameStr = std::string(packageName_cstr); env->ReleaseStringUTFChars(packageName, packageName_cstr); } // Get version code from package info packageManagerObj = env->CallObjectMethod(context, getPackageManager); packageInfoObj = env->CallObjectMethod(packageManagerObj,getPackageInfo, packageName, 0x0); int versionCode = env->GetIntField( packageInfoObj, versionCodeFid); return versionCode; } } // namespace apk_utils namespace file_utils { // Creates the directory if it does not exist. Returns true if the directory // already existed or could be created. bool CheckAndCreateDir(const std::string& path) { struct stat sb; int32_t res = stat(path.c_str(), &sb); if (0 == res && sb.st_mode & S_IFDIR) { ALOGV("Directory %s already exists", path.c_str()); return true; } else if (ENOENT == errno) { ALOGI("Creating directory %s", path.c_str()); res = mkdir(path.c_str(), 0770); if(res!=0) ALOGW("Error creating directory %s: %d", path.c_str(), res); return res==0; } return false; } bool FileExists(const std::string& fname) { struct stat buffer; return (stat(fname.c_str(), &buffer)==0); } std::string GetAppCacheDir(JNIEnv* env, jobject activity) { jclass activityClass = env->FindClass( "android/app/NativeActivity" ); jmethodID getCacheDir = env->GetMethodID( activityClass, "getCacheDir", "()Ljava/io/File;" ); jobject cache_dir = env->CallObjectMethod( activity, getCacheDir ); jclass fileClass = env->FindClass( "java/io/File" ); jmethodID getPath = env->GetMethodID( fileClass, "getPath", "()Ljava/lang/String;" ); jstring path_string = (jstring)env->CallObjectMethod( cache_dir, getPath ); const char *path_chars = env->GetStringUTFChars( path_string, NULL ); std::string temp_folder( path_chars ); env->ReleaseStringUTFChars( path_string, path_chars ); return temp_folder; } } // namespace file_utils std::string UniqueId(JNIEnv* env) { jclass uuid_class = env->FindClass("java/util/UUID"); jmethodID randomUUID = env->GetStaticMethodID( uuid_class, "randomUUID", "()Ljava/util/UUID;"); jobject uuid = env->CallStaticObjectMethod(uuid_class, randomUUID); jmethodID toString = env->GetMethodID( uuid_class, "toString", "()Ljava/lang/String;"); jstring uuid_string = (jstring)env->CallObjectMethod(uuid, toString); const char *uuid_chars = env->GetStringUTFChars( uuid_string, NULL ); std::string temp_uuid( uuid_chars ); env->ReleaseStringUTFChars( uuid_string, uuid_chars ); return temp_uuid; } } // namespace tuningfork