C++程序  |  156行  |  6.14 KB

/*
 * 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