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