1 /*
2  * Copyright (C) 2014 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 #define LOG_TAG "SplitApp"
18 
19 #include <android/log.h>
20 #include <stdio.h>
21 #include <dlfcn.h>
22 
23 #include "jni.h"
24 
25 #define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
26 #define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
27 
28 typedef int (*pFuncGetNumber)();
29 
get_number_from_other_library(const char * library_file_name,const char * function_name)30 static jint get_number_from_other_library(
31         const char* library_file_name, const char* function_name) {
32     void *handle;
33     char *error;
34     handle = dlopen (library_file_name, RTLD_LAZY);
35     if (!handle) {
36         LOGE("Can't load %s: %s\n", library_file_name, dlerror());
37         return -1;
38     }
39     pFuncGetNumber functionGetNumber = (pFuncGetNumber) dlsym(handle, function_name);
40     if ((error = dlerror()) != NULL)  {
41         LOGE("Can't load function %s: %s\n", function_name, error);
42         dlclose(handle);
43         return -2;
44     }
45     int ret = functionGetNumber();
46     dlclose(handle);
47 
48     return ret;
49 }
50 
get_number_a_via_proxy(JNIEnv * env,jobject thiz)51 static jint get_number_a_via_proxy(JNIEnv *env, jobject thiz) {
52     return get_number_from_other_library("libsplitapp_number_proxy.so", "get_number_a");
53 }
54 
get_number_b_via_proxy(JNIEnv * env,jobject thiz)55 static jint get_number_b_via_proxy(JNIEnv *env, jobject thiz) {
56     return get_number_from_other_library("libsplitapp_number_proxy.so", "get_number_b");
57 }
58 
get_number_a_from_provider(JNIEnv * env,jobject thiz)59 static jint get_number_a_from_provider(JNIEnv *env, jobject thiz) {
60     return get_number_from_other_library("libsplitapp_number_provider_a.so", "get_number");
61 }
62 
get_number_b_from_provider(JNIEnv * env,jobject thiz)63 static jint get_number_b_from_provider(JNIEnv *env, jobject thiz) {
64     return get_number_from_other_library("libsplitapp_number_provider_b.so", "get_number");
65 }
66 
67 #ifdef __LIVE_ONLY_32BIT__
68 #define ABI_BITNESS 32
69 #else // __LIVE_ONLY_32BIT__
70 #define ABI_BITNESS 64
71 #endif // __LIVE_ONLY_32BIT__
72 
get_abi_bitness(JNIEnv * env,jobject thiz)73 static jint get_abi_bitness(JNIEnv* env, jobject thiz) {
74     return ABI_BITNESS;
75 }
76 
add(JNIEnv * env,jobject thiz,jint a,jint b)77 static jint add(JNIEnv *env, jobject thiz, jint a, jint b) {
78     int result = a + b;
79     LOGI("%d + %d = %d", a, b, result);
80     return result;
81 }
82 
arch(JNIEnv * env,jobject thiz)83 static jstring arch(JNIEnv *env, jobject thiz) {
84     return env->NewStringUTF(__ANDROID_ARCH__);
85 }
86 
sub(JNIEnv * env,jobject thiz,jint a,jint b)87 static jint sub(JNIEnv* env, jobject thiz, jint a, jint b) {
88 #ifdef __REVISION_HAVE_SUB__
89     int result = a - b;
90     LOGI("%d - %d = %d", a, b, result);
91     return result;
92 #else  // __REVISION_HAVE_SUB__
93     LOGI("Implement sub badly, just return 0");
94     return 0;
95 #endif // __REVISION_HAVE_SUB__
96 }
97 
98 static const char *classPathName = "com/android/cts/splitapp/Native";
99 
100 static JNINativeMethod methods[] = {
101         {"getAbiBitness", "()I", (void*)get_abi_bitness},
102         {"add", "(II)I", (void*)add},
103         {"arch", "()Ljava/lang/String;", (void*)arch},
104         {"sub", "(II)I", (void*)sub},
105         {"getNumberAViaProxy", "()I", (void*) get_number_a_via_proxy},
106         {"getNumberBViaProxy", "()I", (void*) get_number_b_via_proxy},
107         {"getNumberADirectly", "()I", (void*) get_number_a_from_provider},
108         {"getNumberBDirectly", "()I", (void*) get_number_b_from_provider},
109 };
110 
registerNativeMethods(JNIEnv * env,const char * className,JNINativeMethod * gMethods,int numMethods)111 static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) {
112     jclass clazz;
113 
114     clazz = env->FindClass(className);
115     if (clazz == NULL) {
116         LOGE("Native registration unable to find class '%s'", className);
117         return JNI_FALSE;
118     }
119     if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
120         LOGE("RegisterNatives failed for '%s'", className);
121         return JNI_FALSE;
122     }
123 
124     return JNI_TRUE;
125 }
126 
registerNatives(JNIEnv * env)127 static int registerNatives(JNIEnv* env) {
128     if (!registerNativeMethods(env, classPathName, methods, sizeof(methods) / sizeof(methods[0]))) {
129         return JNI_FALSE;
130     }
131 
132     return JNI_TRUE;
133 }
134 
135 typedef union {
136     JNIEnv* env;
137     void* venv;
138 } UnionJNIEnvToVoid;
139 
JNI_OnLoad(JavaVM * vm,void * reserved)140 jint JNI_OnLoad(JavaVM* vm, void* reserved) {
141     UnionJNIEnvToVoid uenv;
142     uenv.venv = NULL;
143     jint result = -1;
144     JNIEnv* env = NULL;
145 
146 #ifdef __REVISION_HAVE_SUB__
147     LOGI("JNI_OnLoad revision %d bits", ABI_BITNESS);
148 #else  // __REVISION_HAVE_SUB__
149     LOGI("JNI_OnLoad %d bits", ABI_BITNESS);
150 #endif // __REVISION_HAVE_SUB__
151 
152     if (vm->GetEnv(&uenv.venv, JNI_VERSION_1_4) != JNI_OK) {
153         LOGE("ERROR: GetEnv failed");
154         goto bail;
155     }
156     env = uenv.env;
157 
158     if (registerNatives(env) != JNI_TRUE) {
159         LOGE("ERROR: registerNatives failed");
160         goto bail;
161     }
162 
163     result = JNI_VERSION_1_4;
164 
165 bail:
166     return result;
167 }
168