1 /*
2 * Copyright 2019 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 "tuningfork_utils.h"
18
19 #include <sys/stat.h>
20 #include <errno.h>
21
22 #define LOG_TAG "TuningFork"
23 #include "Log.h"
24
25 #include <android/asset_manager.h>
26 #include <android/asset_manager_jni.h>
27
28 namespace tuningfork {
29
30 namespace apk_utils {
31
32 // Get an asset from this APK's asset directory.
33 // Returns NULL if the asset could not be found.
34 // Asset_close must be called once the asset is no longer needed.
GetAsset(JNIEnv * env,jobject activity,const char * name)35 AAsset* GetAsset(JNIEnv* env, jobject activity, const char* name) {
36 jclass cls = env->FindClass("android/content/Context");
37 jmethodID get_assets = env->GetMethodID(cls, "getAssets",
38 "()Landroid/content/res/AssetManager;");
39 if(get_assets==nullptr) {
40 ALOGE("No Context.getAssets() method");
41 return nullptr;
42 }
43 auto javaMgr = env->CallObjectMethod(activity, get_assets);
44 if (javaMgr == nullptr) {
45 ALOGE("No java asset manager");
46 return nullptr;
47 }
48 AAssetManager* mgr = AAssetManager_fromJava(env, javaMgr);
49 if (mgr == nullptr) {
50 ALOGE("No asset manager");
51 return nullptr;
52 }
53 AAsset* asset = AAssetManager_open(mgr, name,
54 AASSET_MODE_BUFFER);
55 if (asset == nullptr) {
56 ALOGW("Can't find %s in APK", name);
57 return nullptr;
58 }
59 return asset;
60 }
61
62
63 // Get the app's version code. Also fills packageNameStr with the package name
64 // if it is non-null.
GetVersionCode(JNIEnv * env,jobject context,std::string * packageNameStr)65 int GetVersionCode(JNIEnv *env, jobject context, std::string* packageNameStr) {
66 jstring packageName;
67 jobject packageManagerObj;
68 jobject packageInfoObj;
69 jclass contextClass = env->GetObjectClass( context);
70 jmethodID getPackageNameMid = env->GetMethodID( contextClass, "getPackageName",
71 "()Ljava/lang/String;");
72 jmethodID getPackageManager = env->GetMethodID( contextClass, "getPackageManager",
73 "()Landroid/content/pm/PackageManager;");
74
75 jclass packageManagerClass = env->FindClass("android/content/pm/PackageManager");
76 jmethodID getPackageInfo = env->GetMethodID( packageManagerClass, "getPackageInfo",
77 "(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;");
78
79 jclass packageInfoClass = env->FindClass("android/content/pm/PackageInfo");
80 jfieldID versionCodeFid = env->GetFieldID( packageInfoClass, "versionCode", "I");
81
82 packageName = (jstring)env->CallObjectMethod(context, getPackageNameMid);
83
84 if (packageNameStr != nullptr) {
85 // Fill packageNameStr with the package name
86 const char* packageName_cstr = env->GetStringUTFChars(packageName, NULL);
87 *packageNameStr = std::string(packageName_cstr);
88 env->ReleaseStringUTFChars(packageName, packageName_cstr);
89 }
90 // Get version code from package info
91 packageManagerObj = env->CallObjectMethod(context, getPackageManager);
92 packageInfoObj = env->CallObjectMethod(packageManagerObj,getPackageInfo,
93 packageName, 0x0);
94 int versionCode = env->GetIntField( packageInfoObj, versionCodeFid);
95 return versionCode;
96 }
97
98 } // namespace apk_utils
99
100 namespace file_utils {
101
102 // Creates the directory if it does not exist. Returns true if the directory
103 // already existed or could be created.
CheckAndCreateDir(const std::string & path)104 bool CheckAndCreateDir(const std::string& path) {
105 struct stat sb;
106 int32_t res = stat(path.c_str(), &sb);
107 if (0 == res && sb.st_mode & S_IFDIR) {
108 ALOGV("Directory %s already exists", path.c_str());
109 return true;
110 } else if (ENOENT == errno) {
111 ALOGI("Creating directory %s", path.c_str());
112 res = mkdir(path.c_str(), 0770);
113 if(res!=0)
114 ALOGW("Error creating directory %s: %d", path.c_str(), res);
115 return res==0;
116 }
117 return false;
118 }
FileExists(const std::string & fname)119 bool FileExists(const std::string& fname) {
120 struct stat buffer;
121 return (stat(fname.c_str(), &buffer)==0);
122 }
GetAppCacheDir(JNIEnv * env,jobject activity)123 std::string GetAppCacheDir(JNIEnv* env, jobject activity) {
124 jclass activityClass = env->FindClass( "android/app/NativeActivity" );
125 jmethodID getCacheDir = env->GetMethodID( activityClass, "getCacheDir",
126 "()Ljava/io/File;" );
127 jobject cache_dir = env->CallObjectMethod( activity, getCacheDir );
128
129 jclass fileClass = env->FindClass( "java/io/File" );
130 jmethodID getPath = env->GetMethodID( fileClass, "getPath", "()Ljava/lang/String;" );
131 jstring path_string = (jstring)env->CallObjectMethod( cache_dir, getPath );
132
133 const char *path_chars = env->GetStringUTFChars( path_string, NULL );
134 std::string temp_folder( path_chars );
135 env->ReleaseStringUTFChars( path_string, path_chars );
136
137 return temp_folder;
138 }
139
140 } // namespace file_utils
141
UniqueId(JNIEnv * env)142 std::string UniqueId(JNIEnv* env) {
143 jclass uuid_class = env->FindClass("java/util/UUID");
144 jmethodID randomUUID = env->GetStaticMethodID( uuid_class, "randomUUID",
145 "()Ljava/util/UUID;");
146 jobject uuid = env->CallStaticObjectMethod(uuid_class, randomUUID);
147 jmethodID toString = env->GetMethodID( uuid_class, "toString", "()Ljava/lang/String;");
148 jstring uuid_string = (jstring)env->CallObjectMethod(uuid, toString);
149 const char *uuid_chars = env->GetStringUTFChars( uuid_string, NULL );
150 std::string temp_uuid( uuid_chars );
151 env->ReleaseStringUTFChars( uuid_string, uuid_chars );
152 return temp_uuid;
153 }
154
155 } // namespace tuningfork
156