1/*
2 * Copyright 2016, 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
17namespace android {
18
19/* JNI Helpers for wifi_hal to WifiNative bridge implementation */
20
21class JNIHelper;
22
23template<typename T>
24class JNIObject {
25protected:
26    JNIHelper &mHelper;
27    T mObj;
28public:
29    JNIObject(JNIHelper &helper, T obj);
30    JNIObject(const JNIObject<T>& rhs);
31    virtual ~JNIObject();
32    JNIHelper& getHelper() const {
33        return mHelper;
34    }
35    T get() const {
36        return mObj;
37    }
38    operator T() const {
39        return mObj;
40    }
41    bool isNull() const {
42        return mObj == NULL;
43    }
44    void release();
45    T detach() {
46        T tObj = mObj;
47        mObj = NULL;
48        return tObj;
49    }
50    T clone();
51    JNIObject<T>& operator = (const JNIObject<T>& rhs) {
52        release();
53        mHelper = rhs.mHelper;
54        mObj = rhs.mObj;
55        return *this;
56    }
57    void print() {
58        ALOGD("holding %p", mObj);
59    }
60
61private:
62    template<typename T2>
63    JNIObject(const JNIObject<T2>& rhs);
64};
65
66class JNIHelper {
67    JavaVM *mVM;
68    JNIEnv *mEnv;
69
70public :
71    JNIHelper(JavaVM *vm);
72    JNIHelper(JNIEnv *env);
73    ~JNIHelper();
74
75    void throwException(const char *message, int line);
76
77    /* helpers to deal with members */
78    jboolean getBoolField(jobject obj, const char *name);
79    jint getIntField(jobject obj, const char *name);
80    jlong getLongField(jobject obj, const char *name);
81    JNIObject<jstring> getStringField(jobject obj, const char *name);
82    bool getStringFieldValue(jobject obj, const char *name, char *buf, int size);
83    JNIObject<jobject> getObjectField(jobject obj, const char *name, const char *type);
84    JNIObject<jobjectArray> getArrayField(jobject obj, const char *name, const char *type);
85    void getByteArrayField(jobject obj, const char *name, byte* buf, int size);
86    jlong getLongArrayField(jobject obj, const char *name, int index);
87    JNIObject<jobject> getObjectArrayField(
88            jobject obj, const char *name, const char *type, int index);
89    void setIntField(jobject obj, const char *name, jint value);
90    void setByteField(jobject obj, const char *name, jbyte value);
91    jbyte getByteField(jobject obj, const char *name);
92    void setBooleanField(jobject obj, const char *name, jboolean value);
93    void setLongField(jobject obj, const char *name, jlong value);
94    void setLongArrayField(jobject obj, const char *name, jlongArray value);
95    void setLongArrayElement(jobject obj, const char *name, int index, jlong value);
96    jboolean setStringField(jobject obj, const char *name, const char *value);
97    void reportEvent(jclass cls, const char *method, const char *signature, ...);
98    JNIObject<jobject> createObject(const char *className);
99    JNIObject<jobject> createObjectWithArgs(const char *className, const char *signature, ...);
100    JNIObject<jobjectArray> createObjectArray(const char *className, int size);
101    void setObjectField(jobject obj, const char *name, const char *type, jobject value);
102    void callMethod(jobject obj, const char *method, const char *signature, ...);
103
104    /* helpers to deal with static members */
105    jlong getStaticLongField(jobject obj, const char *name);
106    jlong getStaticLongField(jclass cls, const char *name);
107    void setStaticLongField(jobject obj, const char *name, jlong value);
108    void setStaticLongField(jclass cls, const char *name, jlong value);
109    jlong getStaticLongArrayField(jobject obj, const char *name, int index);
110    jlong getStaticLongArrayField(jclass cls, const char *name, int index);
111    void setStaticLongArrayField(jobject obj, const char *name, jlongArray value);
112    void setStaticLongArrayField(jclass obj, const char *name, jlongArray value);
113    jboolean callStaticMethod(jclass cls, const char *method, const char *signature, ...);
114
115    JNIObject<jobject> getObjectArrayElement(jobjectArray array, int index);
116    JNIObject<jobject> getObjectArrayElement(jobject array, int index);
117    int getArrayLength(jarray array);
118    JNIObject<jobjectArray> newObjectArray(int num, const char *className, jobject val);
119    JNIObject<jbyteArray> newByteArray(int num);
120    JNIObject<jintArray> newIntArray(int num);
121    JNIObject<jlongArray> newLongArray(int num);
122    JNIObject<jstring> newStringUTF(const char *utf);
123    void setObjectArrayElement(jobjectArray array, int index, jobject obj);
124    void setByteArrayRegion(jbyteArray array, int from, int to, const jbyte *bytes);
125    void setIntArrayRegion(jintArray array, int from, int to, const jint *ints);
126    void setLongArrayRegion(jlongArray array, int from, int to, const jlong *longs);
127
128    jobject newGlobalRef(jobject obj);
129    void deleteGlobalRef(jobject obj);
130
131private:
132    /* Jni wrappers */
133    friend class JNIObject<jobject>;
134    friend class JNIObject<jstring>;
135    friend class JNIObject<jobjectArray>;
136    friend class JNIObject<jclass>;
137    friend class JNIObject<jlongArray>;
138    friend class JNIObject<jbyteArray>;
139    friend class JNIObject<jintArray>;
140    jobject newLocalRef(jobject obj);
141    void deleteLocalRef(jobject obj);
142};
143
144template<typename T>
145JNIObject<T>::JNIObject(JNIHelper &helper, T obj)
146    : mHelper(helper), mObj(obj)
147{ }
148
149template<typename T>
150JNIObject<T>::JNIObject(const JNIObject<T>& rhs)
151    : mHelper(rhs.mHelper), mObj(NULL)
152{
153    mObj = (T)mHelper.newLocalRef(rhs.mObj);
154}
155
156template<typename T>
157JNIObject<T>::~JNIObject() {
158    release();
159}
160
161template<typename T>
162void JNIObject<T>::release()
163{
164    if (mObj != NULL) {
165        mHelper.deleteLocalRef(mObj);
166        mObj = NULL;
167    }
168}
169
170template<typename T>
171T JNIObject<T>::clone()
172{
173    return mHelper.newLocalRef(mObj);
174}
175
176}
177
178#define THROW(env, message)      (env).throwException(message, __LINE__)
179