1 /*
2  * Copyright (C) 2015 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 package com.android.server.wifi;
18 
19 import android.os.Bundle;
20 import android.util.Log;
21 
22 import com.android.server.wifi.WifiNative;
23 
24 import org.json.JSONArray;
25 import org.json.JSONException;
26 import org.json.JSONObject;
27 
28 import java.lang.reflect.Field;
29 import java.util.Iterator;
30 
31 public class HalMockUtils {
32     private static final String TAG = "HalMockUtils";
33     private static final boolean DBG = true;
34     private static final boolean VDBG = true;
35 
initHalMock()36     private static native int initHalMock();
37 
setHalMockObject(Object obj)38     public static native void setHalMockObject(Object obj);
39 
40     static {
41         System.loadLibrary("wifi-hal-mock");
42     }
43 
initHalMockLibrary()44     public static void initHalMockLibrary() throws Exception {
45         /*
46          * Setting the Wi-Fi HAL handle and interface (array) to dummy
47          * values. Required to fake the init checking code to think that
48          * the HAL actually started.
49          *
50          * Note that values are not important since they are only used by
51          * the real HAL - which is mocked-out in this use-case.
52          */
53         Field field = WifiNative.class.getDeclaredField("sWifiHalHandle");
54         field.setAccessible(true);
55         long currentWifiHalHandle = field.getLong(null);
56         if (DBG) Log.d(TAG, "currentWifiHalHandle=" + currentWifiHalHandle);
57         if (currentWifiHalHandle == 0) {
58             field.setLong(null, 5);
59 
60             field = WifiNative.class.getDeclaredField("sWifiIfaceHandles");
61             field.setAccessible(true);
62             long[] wifiIfaceHandles = {
63                     10 };
64             field.set(null, wifiIfaceHandles);
65         }
66 
67         initHalMock();
68     }
69 
70     /*
71      * JSON data-model for passing arguments between mock host (java) and mock
72      * HAL (C):
73      * {
74      *      "name" : { "type" : "int|byte_array", "value" : 123 | [1, 2, 3, 4] }
75      * }
76      */
77 
78     private static final String TYPE_KEY = "type";
79     private static final String VALUE_KEY = "value";
80 
81     private static final String TYPE_INT = "int";
82     private static final String TYPE_BYTE_ARRAY = "byte_array";
83 
convertJsonToBundle(String jsonArgs)84     public static Bundle convertJsonToBundle(String jsonArgs) throws JSONException {
85         if (VDBG) Log.v(TAG, "convertJsonToBundle: jsonArgs=" + jsonArgs);
86 
87         Bundle bundle = new Bundle();
88 
89         JSONObject jsonObject = new JSONObject(jsonArgs);
90         Iterator<String> iter = jsonObject.keys();
91         while (iter.hasNext()) {
92             String key = iter.next();
93             JSONObject field = jsonObject.optJSONObject(key);
94 
95             String type = field.getString(TYPE_KEY);
96 
97             if (TYPE_INT.equals(type)) {
98                 bundle.putInt(key, field.optInt(VALUE_KEY));
99             } else if (TYPE_BYTE_ARRAY.equals(type)) {
100                 JSONArray array = field.optJSONArray(VALUE_KEY);
101                 byte[] bArray = new byte[array.length()];
102                 for (int i = 0; i < array.length(); ++i) {
103                     bArray[i] = (byte) array.getInt(i);
104                 }
105                 bundle.putByteArray(key, bArray);
106             } else {
107                 throw new JSONException("Unexpected TYPE read from mock HAL -- '" + type + "'");
108             }
109         }
110 
111         if (DBG) Log.d(TAG, "convertJsonToBundle: returning bundle=" + bundle);
112         return bundle;
113     }
114 
convertBundleToJson(Bundle bundle)115     public static JSONObject convertBundleToJson(Bundle bundle) throws JSONException {
116         if (VDBG) Log.v(TAG, "convertBundleToJson: bundle=" + bundle.toString());
117 
118         JSONObject json = new JSONObject();
119         for (String key : bundle.keySet()) {
120             Object value = bundle.get(key);
121             JSONObject child = new JSONObject();
122             if (value instanceof Integer) {
123                 child.put(TYPE_KEY, TYPE_INT);
124                 child.put(VALUE_KEY, ((Integer) value).intValue());
125             } else if (value instanceof byte[]) {
126                 byte[] array = (byte[]) value;
127                 JSONArray jsonArray = new JSONArray();
128                 for (int i = 0; i < array.length; ++i) {
129                     jsonArray.put(array[i]);
130                 }
131                 child.put(TYPE_KEY, TYPE_BYTE_ARRAY);
132                 child.put(VALUE_KEY, jsonArray);
133             } else {
134                 throw new JSONException("Unexpected type of JSON tree node (not an Integer "
135                         + "or byte[]): " + value);
136             }
137             json.put(key, child);
138         }
139 
140         if (DBG) Log.d(TAG, "convertBundleToJson: returning JSONObject=" + json);
141         return json;
142     }
143 }
144