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 
17 #include <stdint.h>
18 #include "JniConstants.h"
19 #include <ScopedUtfChars.h>
20 #include <ScopedBytes.h>
21 #include <utils/misc.h>
22 #include <android_runtime/AndroidRuntime.h>
23 #include <utils/Log.h>
24 #include <utils/String16.h>
25 #include <ctype.h>
26 #include <sys/socket.h>
27 #include <linux/if.h>
28 #include "wifi.h"
29 #include "wifi_hal.h"
30 #include "jni_helper.h"
31 #include "wifi_hal_mock.h"
32 #include <sstream>
33 #include <rapidjson/document.h>
34 #include <rapidjson/stringbuffer.h>
35 #include <rapidjson/writer.h>
36 
37 namespace android {
38 
39 jobject mock_mObj; /* saved HalMock object (not class!) */
40 JavaVM* mock_mVM = NULL; /* saved JVM pointer */
41 
42 /* Variable and function declared and defined in:
43  *  com_android_server_wifi_nan_WifiNanNative.cpp
44  */
45 extern wifi_hal_fn hal_fn;
46 extern "C" jint Java_com_android_server_wifi_WifiNative_registerNatives(
47     JNIEnv* env, jclass clazz);
48 
49 namespace hal_json_tags {
50 static constexpr const char* const type_tag = "type";
51 static constexpr const char* const value_tag = "value";
52 
53 static constexpr const char* const type_int_tag = "int";
54 static constexpr const char* const type_byte_array_tag = "byte_array";
55 }
56 
HalMockJsonWriter()57 HalMockJsonWriter::HalMockJsonWriter()
58     : allocator(doc.GetAllocator()) {
59   doc.SetObject();
60 }
61 
put_int(const char * name,int x)62 void HalMockJsonWriter::put_int(const char* name, int x) {
63   rapidjson::Value object(rapidjson::kObjectType);
64   object.AddMember(
65       rapidjson::Value(hal_json_tags::type_tag,
66                        strlen(hal_json_tags::type_tag)),
67       rapidjson::Value(hal_json_tags::type_int_tag,
68                        strlen(hal_json_tags::type_int_tag)),
69       allocator);
70   object.AddMember(
71       rapidjson::Value(hal_json_tags::value_tag,
72                        strlen(hal_json_tags::value_tag)),
73       rapidjson::Value(x), allocator);
74   doc.AddMember(rapidjson::Value(name, strlen(name)), object, allocator);
75 }
76 
put_byte_array(const char * name,u8 * byte_array,int array_length)77 void HalMockJsonWriter::put_byte_array(const char* name, u8* byte_array,
78                                        int array_length) {
79   rapidjson::Value object(rapidjson::kObjectType);
80   object.AddMember(
81       rapidjson::Value(hal_json_tags::type_tag,
82                        strlen(hal_json_tags::type_tag)),
83       rapidjson::Value(hal_json_tags::type_byte_array_tag,
84                        strlen(hal_json_tags::type_byte_array_tag)),
85       allocator);
86 
87   rapidjson::Value array(rapidjson::kArrayType);
88   for (int i = 0; i < array_length; ++i) {
89     array.PushBack((int) byte_array[i], allocator);
90   }
91 
92   object.AddMember(
93       rapidjson::Value(hal_json_tags::value_tag,
94                        strlen(hal_json_tags::value_tag)),
95       array, allocator);
96   doc.AddMember(rapidjson::Value(name, strlen(name)), object, allocator);
97 }
98 
to_string()99 std::string HalMockJsonWriter::to_string() {
100   rapidjson::StringBuffer strbuf;
101   rapidjson::Writer < rapidjson::StringBuffer > writer(strbuf);
102   doc.Accept(writer);
103   return strbuf.GetString();
104 }
105 
HalMockJsonReader(const char * str)106 HalMockJsonReader::HalMockJsonReader(const char* str) {
107   doc.Parse(str);
108   assert(doc.IsObject());
109 }
110 
get_int(const char * key,bool * error)111 int HalMockJsonReader::get_int(const char* key, bool* error) {
112   if (!doc.HasMember(key)) {
113     *error = true;
114     ALOGE("get_int: can't find %s key", key);
115     return 0;
116   }
117   const rapidjson::Value& element = doc[key];
118   if (!element.HasMember(hal_json_tags::value_tag)) {
119     *error = true;
120     ALOGE("get_int: can't find the 'value' sub-key for %s key", key);
121     return 0;
122   }
123   const rapidjson::Value& value = element[hal_json_tags::value_tag];
124   if (!value.IsInt()) {
125     *error = true;
126     ALOGE("get_int: the value isn't an 'int' for the %s key", key);
127     return 0;
128   }
129   return value.GetInt();
130 }
131 
get_byte_array(const char * key,bool * error,u8 * array,unsigned int max_array_size)132 void HalMockJsonReader::get_byte_array(const char* key, bool* error, u8* array,
133                                        unsigned int max_array_size) {
134   if (!doc.HasMember(key)) {
135     *error = true;
136     ALOGE("get_byte_array: can't find %s key", key);
137     return;
138   }
139   const rapidjson::Value& element = doc[key];
140   if (!element.HasMember(hal_json_tags::value_tag)) {
141     *error = true;
142     ALOGE("get_byte_array: can't find the 'value' sub-key for %s key", key);
143     return;
144   }
145   const rapidjson::Value& value = element[hal_json_tags::value_tag];
146   if (!value.IsArray()) {
147     *error = true;
148     ALOGE("get_byte_array: the value isn't an 'array' for the %s key", key);
149     return;
150   }
151 
152   if (value.Size() > max_array_size) {
153     *error = true;
154     ALOGE("get_byte_array: size of array (%d) is larger than maximum "
155           "allocated (%d)",
156           value.Size(), max_array_size);
157     return;
158   }
159 
160   for (unsigned int i = 0; i < value.Size(); ++i) {
161     const rapidjson::Value& item = value[i];
162     if (!item.IsInt()) {
163       *error = true;
164       ALOGE("get_byte_array: the value isn't an 'int' for the %s[%d] key", key,
165             i);
166       return;
167     }
168     array[i] = item.GetInt();
169   }
170 }
171 
172 
init_wifi_hal_func_table_mock(wifi_hal_fn * fn)173 int init_wifi_hal_func_table_mock(wifi_hal_fn *fn) {
174   if (fn == NULL) {
175     return -1;
176   }
177 
178   /* TODO: add other Wi-Fi HAL registrations here - once you have mocks */
179 
180   return 0;
181 }
182 
Java_com_android_server_wifi_HalMockUtils_initHalMock(JNIEnv * env,jclass clazz)183 extern "C" jint Java_com_android_server_wifi_HalMockUtils_initHalMock(
184     JNIEnv* env, jclass clazz) {
185   env->GetJavaVM(&mock_mVM);
186 
187   Java_com_android_server_wifi_WifiNative_registerNatives(env, clazz);
188   return init_wifi_hal_func_table_mock(&hal_fn);
189 }
190 
Java_com_android_server_wifi_HalMockUtils_setHalMockObject(JNIEnv * env,jclass clazz,jobject hal_mock_object)191 extern "C" void Java_com_android_server_wifi_HalMockUtils_setHalMockObject(
192     JNIEnv* env, jclass clazz, jobject hal_mock_object) {
193   mock_mObj = (jobject) env->NewGlobalRef(hal_mock_object);
194 }
195 
196 }  // namespace android
197