cocos-engine-external/sources/Swappy/src/common/jni/jni_wrap.h

640 lines
22 KiB
C++

/*
* 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.
*/
#pragma once
#include <sstream>
#include "jni/jni_helper.h"
namespace gamesdk {
namespace jni {
namespace java {
class Object {
public:
LocalObject obj_;
Object(const char* className, const char* ctorSig, ...) {
va_list argptr;
va_start(argptr, ctorSig);
obj_ = NewObjectV(className, ctorSig, argptr);
va_end(argptr);
}
Object(LocalObject&& o) : obj_(std::move(o)) {}
Object(jobject o) {
// If there's an exception pending, don't store the reference as it may
// be invalid and cause a crash on some devices when released.
if (!RawExceptionCheck()) {
obj_ = o;
obj_.Cast(); // Cast to the object's own class.
}
}
bool valid() const { return !obj_.ClassIsNull(); }
void CallVVMethod(const char* name) { obj_.CallVoidMethod(name, "()V"); }
void CallIVMethod(const char* name, int a) {
obj_.CallVoidMethod(name, "(I)V", a);
}
int CallVIMethod(const char* name) {
return obj_.CallIntMethod(name, "()I");
}
int CallIIMethod(const char* name, const int a) {
return obj_.CallIntMethod(name, "(I)I", a);
}
void CallZVMethod(const char* name, bool a) {
obj_.CallVoidMethod(name, "(Z)V", a);
}
void CallSVMethod(const char* name, const char* a) {
obj_.CallVoidMethod(name, "(Ljava/lang/String;)V", String(a).J());
}
String CallVSMethod(const char* name) {
return obj_.CallStringMethod(name, "()Ljava/lang/String;");
}
void CallSSVMethod(const char* name, const char* a, const char* b) {
obj_.CallVoidMethod(name, "(Ljava/lang/String;Ljava/lang/String;)V",
String(a).J(), String(b).J());
}
Object CallAOMethod(const char* name, const char* returnClass) {
std::stringstream str;
str << "()[L" << returnClass << ";";
jobject o = obj_.CallObjectMethod(name, str.str().c_str());
return Object(o);
}
Object CallVOMethod(const char* name, const char* returnClass) {
std::stringstream str;
str << "()L" << returnClass << ";";
jobject o = obj_.CallObjectMethod(name, str.str().c_str());
return Object(o);
}
Object CallIOMethod(const char* name, int a, const char* returnClass) {
std::stringstream str;
str << "(I)L" << returnClass << ";";
jobject o = obj_.CallObjectMethod(name, str.str().c_str(), a);
return Object(o);
}
void CallOVMethod(const char* name, const char* parameterClassA,
const Object& a) {
std::stringstream str;
str << "(L" << parameterClassA << ";)V";
obj_.CallVoidMethod(name, str.str().c_str(), (jobject)a.obj_);
}
Object CallSIOMethod(const char* name, const char* a, int b,
const char* returnClass) {
std::stringstream str;
str << "(Ljava/lang/String;I)L" << returnClass << ";";
jobject o =
obj_.CallObjectMethod(name, str.str().c_str(), String(a).J(), b);
return Object(o);
}
Object CallOOOMethod(const char* name, const char* parameterClassA,
const Object& a, const char* parameterClassB,
const Object& b, const char* returnClass) {
std::stringstream str;
str << "(L" << parameterClassA << ";L" << parameterClassB << ";)L"
<< returnClass << ";";
jobject o = obj_.CallObjectMethod(name, str.str().c_str(),
(jobject)a.obj_, (jobject)b.obj_);
return Object(o);
}
int CallSIIMethod(const char* name, const char* a, const int b) {
std::stringstream str;
str << "(Ljava/lang/String;I)I";
return obj_.CallIntMethod(name, "(Ljava/lang/String;I)I", String(a).J(),
b);
}
Object CallSIIOMethod(const char* name, const char* a, int b, int c,
const char* returnClass) {
std::stringstream str;
str << "(Ljava/lang/String;II)L" << returnClass << ";";
jobject o =
obj_.CallObjectMethod(name, str.str().c_str(), String(a).J(), b, c);
return Object(o);
}
Object CallSOMethod(const char* name, const char* a,
const char* returnClass) {
std::stringstream str;
str << "(Ljava/lang/String;)L" << returnClass << ";";
jobject o =
obj_.CallObjectMethod(name, str.str().c_str(), String(a).J());
return Object(o);
}
bool CallVZMethod(const char* name) {
return obj_.CallBooleanMethod(name, "()Z");
}
bool IsNull() const { return obj_.IsNull(); }
};
namespace io {
class OutputStream : public Object {
public:
OutputStream(Object&& o) : Object(std::move(o)) {}
void close() { CallVVMethod("close"); }
};
class OutputStreamWriter : public Object {
public:
OutputStreamWriter(OutputStream& o, const std::string& s)
: Object("java/io/OutputStreamWriter",
"(Ljava/io/OutputStream;Ljava/lang/String;)V", (jobject)o.obj_,
String(s.c_str()).J()) {}
};
class Writer : public Object {
public:
Writer(Object&& o) : Object(std::move(o)) {}
void write(const std::string& s) { CallSVMethod("write", s.c_str()); }
void flush() { CallVVMethod("flush"); }
void close() { CallVVMethod("close"); }
};
class BufferedWriter : public Writer {
public:
BufferedWriter(const Writer& w)
: Writer(Object("java/io/BufferedWriter", "(Ljava/io/Writer;)V",
(jobject)w.obj_)) {}
};
class InputStream : public Object {
public:
InputStream(Object&& o) : Object(std::move(o)) {}
void close() { CallVVMethod("close"); }
};
class Reader : public Object {
public:
Reader(Object&& o) : Object(std::move(o)) {}
jni::String readLine() { return CallVSMethod("readLine"); }
void close() { CallVVMethod("close"); }
};
class InputStreamReader : public Reader {
public:
InputStreamReader(const InputStream& is, const std::string& s)
: Reader(Object("java/io/InputStreamReader",
"(Ljava/io/InputStream;Ljava/lang/String;)V",
(jobject)is.obj_, String(s.c_str()).J())) {}
};
class BufferedReader : public Reader {
public:
BufferedReader(const Reader& r)
: Reader(Object("java/io/BufferedReader", "(Ljava/io/Reader;)V",
(jobject)r.obj_)) {}
};
class File : public Object {
public:
File(Object&& o) : Object(std::move(o)) {}
jni::String getPath() { return CallVSMethod("getPath"); }
};
} // namespace io
namespace util {
class UUID : public Object {
public:
UUID(LocalObject&& o) : Object(std::move(o)) {}
static UUID randomUUID() {
LocalObject obj(nullptr, Env()->FindClass("java/util/UUID"));
auto o = obj.CallStaticObjectMethod("randomUUID", "()Ljava/util/UUID;");
obj.SetObj(o);
return obj;
}
jni::String toString() { return CallVSMethod("toString"); }
};
class List : public java::Object {
public:
List(Object&& o) : Object(std::move(o)) {}
java::Object get(int index) {
return CallIOMethod("get", index, "java/lang/Object");
}
bool isEmpty() { return CallVZMethod("isEmpty"); }
jni::String toString() { return CallVSMethod("toString"); }
};
} // namespace util
namespace net {
class URLConnection : public Object {
public:
URLConnection(Object&& o) : Object(std::move(o)) {}
};
class HttpURLConnection : public URLConnection {
public:
HttpURLConnection(URLConnection&& u) : URLConnection(std::move(u)) {
obj_.Cast("java/net/HttpURLConnection");
}
void setRequestMethod(const std::string& method) {
CallSVMethod("setRequestMethod", method.c_str());
}
void setConnectTimeout(int t) { CallIVMethod("setConnectTimeout", t); }
void setReadTimeout(int timeout) {
CallIVMethod("setReadTimeout", timeout);
}
void setDoOutput(bool d) { CallZVMethod("setDoOutput", d); }
void setDoInput(bool d) { CallZVMethod("setDoInput", d); }
void setUseCaches(bool d) { CallZVMethod("setUseCaches", d); }
void setRequestProperty(const std::string& name, const std::string& value) {
CallSSVMethod("setRequestProperty", name.c_str(), value.c_str());
}
io::OutputStream getOutputStream() {
return CallVOMethod("getOutputStream", "java/io/OutputStream");
}
void connect() { CallVVMethod("connect"); }
void disconnect() { CallVVMethod("disconnect"); }
int getResponseCode() { return CallVIMethod("getResponseCode"); }
jni::String getResponseMessage() {
return CallVSMethod("getResponseMessage");
}
io::InputStream getInputStream() {
return CallVOMethod("getInputStream", "java/io/InputStream");
}
};
class URL : public Object {
public:
URL(LocalObject o) : Object(o) {}
URL(const std::string& s)
: Object("java/net/URL", "(Ljava/lang/String;)V",
String(s.c_str()).J()) {}
URLConnection openConnection() {
return URLConnection(Object(obj_.CallObjectMethod(
"openConnection", "()Ljava/net/URLConnection;")));
}
};
} // namespace net
namespace security {
class MessageDigest : public java::Object {
public:
MessageDigest(const std::string& instance) : java::Object(nullptr) {
LocalObject temp(nullptr, FindClass("java/security/MessageDigest"));
auto o = temp.CallStaticObjectMethod(
"getInstance", "(Ljava/lang/String;)Ljava/security/MessageDigest;",
String(instance.c_str()).J());
temp.SetObj(o);
obj_ = std::move(temp);
}
std::vector<unsigned char> digest(
const std::vector<unsigned char>& bs) const {
auto env = Env();
jbyteArray jbs = env->NewByteArray(bs.size());
env->SetByteArrayRegion(jbs, 0, bs.size(),
reinterpret_cast<const jbyte*>(bs.data()));
jbyteArray out = reinterpret_cast<jbyteArray>(
obj_.CallObjectMethod("digest", "([B)[B", jbs));
env->DeleteLocalRef(jbs);
return GetByteArrayBytesAndDeleteRef(out);
}
};
} // namespace security
} // namespace java
namespace android {
namespace content {
namespace pm {
class FeatureInfo : public java::Object {
public:
FeatureInfo(java::Object&& o) : java::Object(std::move(o)) {
jni::String jname(
(jstring)obj_.GetObjectField("name", "Ljava/lang/String;")
.ObjNewRef());
if (jname.J() != nullptr) name = jname.C();
reqGlEsVersion = obj_.GetIntField("reqGlEsVersion");
}
static constexpr int GL_ES_VERSION_UNDEFINED = 0x0000000;
std::string name;
int reqGlEsVersion;
};
class ApplicationInfo : public java::Object {
public:
ApplicationInfo(java::Object&& o) : java::Object(std::move(o)) {}
int flags() const { return obj_.GetIntField("flags"); }
static const int FLAG_DEBUGGABLE = 2;
};
class PackageInfo : public java::Object {
public:
PackageInfo(java::Object&& o) : java::Object(std::move(o)) {}
typedef std::vector<unsigned char> Signature;
std::vector<Signature> signatures() const {
auto env = Env();
auto jsigs = obj_.GetObjectField("signatures",
"[Landroid/content/pm/Signature;");
jobjectArray sigs = jsigs.AsObjectArray();
if (sigs == nullptr) return {};
int n = env->GetArrayLength(sigs);
if (n > 0) {
std::vector<std::vector<unsigned char>> ret;
for (int i = 0; i < n; ++i) {
Object sig(env->GetObjectArrayElement(sigs, i));
jbyteArray bytes = reinterpret_cast<jbyteArray>(
sig.obj_.CallObjectMethod("toByteArray", "()[B"));
ret.push_back(GetByteArrayBytesAndDeleteRef(bytes));
}
return ret;
} else
return {};
}
int versionCode() const { return obj_.GetIntField("versionCode"); }
ApplicationInfo applicationInfo() const {
auto appInfo = obj_.GetObjectField(
"applicationInfo", "[Landroid/content/pm/ApplicationInfo;");
return ApplicationInfo(std::move(appInfo));
}
};
class PackageManager : public java::Object {
public:
PackageManager(java::Object&& o) : java::Object(std::move(o)) {}
static constexpr int GET_SIGNATURES = 0x0000040;
PackageInfo getPackageInfo(const std::string& name, int flags) {
return CallSIOMethod("getPackageInfo", name.c_str(), flags,
"android/content/pm/PackageInfo");
}
std::vector<FeatureInfo> getSystemAvailableFeatures() {
auto env = Env();
auto jfeatures = CallAOMethod("getSystemAvailableFeatures",
"android/content/pm/FeatureInfo");
if (jfeatures.obj_.IsNull()) return {};
jobjectArray features = jfeatures.obj_.AsObjectArray();
int n = env->GetArrayLength(features);
std::vector<FeatureInfo> ret;
if (n > 0) {
for (int i = 0; i < n; ++i) {
FeatureInfo f(Object(env->GetObjectArrayElement(features, i)));
ret.push_back(std::move(f));
}
}
return ret;
}
};
} // namespace pm
namespace res {
class AssetManager : public java::Object {
public:
AssetManager(java::Object&& o) : java::Object(std::move(o)) {}
};
} // namespace res
class Intent : java::Object {
public:
static constexpr const char* ACTION_BATTERY_CHANGED =
"android.intent.action.BATTERY_CHANGED";
Intent(java::Object&& o) : java::Object(std::move(o)) {}
int getIntExtra(const char* name, int defaultValue) {
return CallSIIMethod("getIntExtra", name, defaultValue);
}
};
class IntentFilter : public java::Object {
public:
IntentFilter(jobject o) : java::Object(o) {}
IntentFilter(const char* action)
: Object("android/content/IntentFilter", "(Ljava/lang/String;)V",
String(action).J()) {}
};
class BroadcastReceiver : public java::Object {
public:
BroadcastReceiver(java::Object&& o) : java::Object(std::move(o)) {}
};
class Context : public java::Object {
public:
static constexpr const char* CONNECTIVITY_SERVICE = "connectivity";
static constexpr const char* BATTERY_SERVICE = "batterymanager";
static constexpr const char* POWER_SERVICE = "power";
static constexpr const char* ACTIVITY_SERVICE = "activity";
Context(jobject o) : java::Object(o) {}
pm::PackageManager getPackageManager() {
return CallVOMethod("getPackageManager",
"android/content/pm/PackageManager");
}
jni::String getPackageName() { return CallVSMethod("getPackageName"); }
res::AssetManager getAssets() {
return CallVOMethod("getAssets", "android/content/res/AssetManager");
}
java::io::File getCacheDir() {
return CallVOMethod("getCacheDir", "java/io/File");
}
java::Object getSystemService(const char* name) {
return CallSOMethod("getSystemService", name, "java/lang/Object");
}
java::Object registerReceiver(BroadcastReceiver& broadcastReceiver,
IntentFilter& intentFilter) {
return CallOOOMethod("registerReceiver",
"android/content/BroadcastReceiver",
broadcastReceiver, "android/content/IntentFilter",
intentFilter, "android/content/Intent");
}
};
} // namespace content
namespace os {
class DebugClass {
jmethodID getNativeHeapAllocatedSize_method_id_;
public:
static uint64_t getNativeHeapAllocatedSize() {
JNIEnv* env = Env();
if (env != nullptr) {
LocalObject obj;
obj.Cast("android/os/Debug");
jclass clz = obj;
jmethodID method = env->GetStaticMethodID(
clz, "getNativeHeapAllocatedSize", "()J");
if (method != NULL)
return (uint64_t)env->CallStaticLongMethod(clz, method);
}
return 0;
}
static uint64_t getNativeHeapFreeSize() {
JNIEnv* env = Env();
if (env != nullptr) {
LocalObject obj;
obj.Cast("android/os/Debug");
jclass clz = obj;
jmethodID method =
env->GetStaticMethodID(clz, "getNativeHeapFreeSize", "()J");
if (method != NULL)
return (uint64_t)env->CallStaticLongMethod(clz, method);
}
return 0;
}
static uint64_t getNativeHeapSize() {
JNIEnv* env = Env();
if (env != nullptr) {
LocalObject obj;
obj.Cast("android/os/Debug");
jclass clz = obj;
jmethodID method =
env->GetStaticMethodID(clz, "getNativeHeapSize", "()J");
if (method != NULL)
return (uint64_t)env->CallStaticLongMethod(clz, method);
}
return 0;
}
static uint64_t getPss() {
JNIEnv* env = Env();
if (env != nullptr) {
LocalObject obj;
obj.Cast("android/os/Debug");
jclass clz = obj;
jmethodID method = env->GetStaticMethodID(clz, "getPss", "()J");
if (method != NULL)
return (uint64_t)env->CallStaticLongMethod(clz, method);
}
return 0;
}
}; // class Debug
class Build {
static constexpr const char class_name[] = "android/os/Build";
public:
static jni::String MODEL() {
return GetStaticStringField(class_name, "MODEL");
}
static jni::String BRAND() {
return GetStaticStringField(class_name, "BRAND");
}
static jni::String PRODUCT() {
return GetStaticStringField(class_name, "PRODUCT");
}
static jni::String DEVICE() {
return GetStaticStringField(class_name, "DEVICE");
}
static jni::String FINGERPRINT() {
return GetStaticStringField(class_name, "FINGERPRINT");
}
static jni::String SOC_MODEL() {
return GetStaticStringField(class_name, "SOC_MODEL");
}
static jni::String SOC_MANUFACTURER() {
return GetStaticStringField(class_name, "SOC_MANUFACTURER");
}
}; // Class Build
class BatteryManager : java::Object {
public:
static constexpr const char* EXTRA_LEVEL = "level";
static constexpr const char* EXTRA_SCALE = "scale";
static constexpr const char* EXTRA_PLUGGED = "plugged";
static constexpr const int BATTERY_PROPERTY_CHARGE_COUNTER = 1;
BatteryManager(java::Object&& o) : java::Object(std::move(o)) {}
int getIntProperty(int id) { return CallIIMethod("getIntProperty", id); }
};
class PowerManager : java::Object {
public:
PowerManager(java::Object&& o) : java::Object(std::move(o)) {}
int getCurrentThermalStatus() {
return CallVIMethod("getCurrentThermalStatus");
}
bool isPowerSaveMode() { return CallVZMethod("isPowerSaveMode"); }
};
} // namespace os
namespace net {
class ConnectivityManager : java::Object {
public:
ConnectivityManager(java::Object&& o) : java::Object(std::move(o)) {}
// NB This requires Manifest.permission.ACCESS_NETWORK_STATE.
bool isActiveNetworkMetered() {
return CallVZMethod("isActiveNetworkMetered");
}
};
} // namespace net
namespace app {
class MemoryInfo : public java::Object {
public:
MemoryInfo(java::Object&& o) : java::Object(std::move(o)) {}
MemoryInfo()
: java::Object("android/app/ActivityManager$MemoryInfo", "()V") {}
int64_t threshold() const { return obj_.GetLongField("threshold"); }
int64_t availMem() const { return obj_.GetLongField("availMem"); }
bool lowMemory() const { return obj_.GetBooleanField("lowMemory"); }
int64_t totalMem() const { return obj_.GetLongField("totalMem"); }
};
class ActivityManager : public java::Object {
public:
ActivityManager(java::Object&& o) : java::Object(std::move(o)) {}
void getMemoryInfo(MemoryInfo& memoryInfo) {
CallOVMethod("getMemoryInfo", "android/app/ActivityManager$MemoryInfo",
memoryInfo);
}
int32_t getMemoryClass() { return CallVIMethod("getMemoryClass"); }
int32_t getLargeMemoryClass() {
return CallVIMethod("getLargeMemoryClass");
}
bool isLowRamDevice() { return CallVZMethod("isLowRamDevice"); }
java::util::List getHistoricalProcessExitReasons(std::string& packageName,
int pid, int maxNum) {
return CallSIIOMethod("getHistoricalProcessExitReasons",
packageName.c_str(), pid, maxNum,
"java/util/List");
}
};
class ApplicationExitInfo : java::Object {
public:
static constexpr int REASON_LOW_MEMORY = 3;
ApplicationExitInfo(java::Object&& o) : java::Object(std::move(o)) {}
int getReason() { return CallVIMethod("getReason"); }
};
} // namespace app
} // namespace android
// A local jni reference to the app context
android::content::Context AppContext();
} // namespace jni
} // namespace gamesdk