1956f54b391677d78379729dd14518edddf3c7660Etan Cohen/*
2956f54b391677d78379729dd14518edddf3c7660Etan Cohen * Copyright (C) 2015 The Android Open Source Project
3956f54b391677d78379729dd14518edddf3c7660Etan Cohen *
4956f54b391677d78379729dd14518edddf3c7660Etan Cohen * Licensed under the Apache License, Version 2.0 (the "License");
5956f54b391677d78379729dd14518edddf3c7660Etan Cohen * you may not use this file except in compliance with the License.
6956f54b391677d78379729dd14518edddf3c7660Etan Cohen * You may obtain a copy of the License at
7956f54b391677d78379729dd14518edddf3c7660Etan Cohen *
8956f54b391677d78379729dd14518edddf3c7660Etan Cohen *      http://www.apache.org/licenses/LICENSE-2.0
9956f54b391677d78379729dd14518edddf3c7660Etan Cohen *
10956f54b391677d78379729dd14518edddf3c7660Etan Cohen * Unless required by applicable law or agreed to in writing, software
11956f54b391677d78379729dd14518edddf3c7660Etan Cohen * distributed under the License is distributed on an "AS IS" BASIS,
12956f54b391677d78379729dd14518edddf3c7660Etan Cohen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13956f54b391677d78379729dd14518edddf3c7660Etan Cohen * See the License for the specific language governing permissions and
14956f54b391677d78379729dd14518edddf3c7660Etan Cohen * limitations under the License.
15956f54b391677d78379729dd14518edddf3c7660Etan Cohen */
16956f54b391677d78379729dd14518edddf3c7660Etan Cohen
1722b4156d2948e3108ae8439dc72f76fb97526aceEtan Cohenpackage com.android.server.wifi;
18956f54b391677d78379729dd14518edddf3c7660Etan Cohen
19956f54b391677d78379729dd14518edddf3c7660Etan Cohenimport android.os.Bundle;
20956f54b391677d78379729dd14518edddf3c7660Etan Cohenimport android.util.Log;
21956f54b391677d78379729dd14518edddf3c7660Etan Cohen
22956f54b391677d78379729dd14518edddf3c7660Etan Cohenimport com.android.server.wifi.WifiNative;
23956f54b391677d78379729dd14518edddf3c7660Etan Cohen
24956f54b391677d78379729dd14518edddf3c7660Etan Cohenimport org.json.JSONArray;
25956f54b391677d78379729dd14518edddf3c7660Etan Cohenimport org.json.JSONException;
26956f54b391677d78379729dd14518edddf3c7660Etan Cohenimport org.json.JSONObject;
27956f54b391677d78379729dd14518edddf3c7660Etan Cohen
28956f54b391677d78379729dd14518edddf3c7660Etan Cohenimport java.lang.reflect.Field;
29956f54b391677d78379729dd14518edddf3c7660Etan Cohenimport java.util.Iterator;
30956f54b391677d78379729dd14518edddf3c7660Etan Cohen
31956f54b391677d78379729dd14518edddf3c7660Etan Cohenpublic class HalMockUtils {
32956f54b391677d78379729dd14518edddf3c7660Etan Cohen    private static final String TAG = "HalMockUtils";
33956f54b391677d78379729dd14518edddf3c7660Etan Cohen    private static final boolean DBG = true;
34956f54b391677d78379729dd14518edddf3c7660Etan Cohen    private static final boolean VDBG = true;
35956f54b391677d78379729dd14518edddf3c7660Etan Cohen
36956f54b391677d78379729dd14518edddf3c7660Etan Cohen    private static native int initHalMock();
37956f54b391677d78379729dd14518edddf3c7660Etan Cohen
38956f54b391677d78379729dd14518edddf3c7660Etan Cohen    public static native void setHalMockObject(Object obj);
39956f54b391677d78379729dd14518edddf3c7660Etan Cohen
40956f54b391677d78379729dd14518edddf3c7660Etan Cohen    static {
41956f54b391677d78379729dd14518edddf3c7660Etan Cohen        System.loadLibrary("wifi-hal-mock");
42956f54b391677d78379729dd14518edddf3c7660Etan Cohen    }
43956f54b391677d78379729dd14518edddf3c7660Etan Cohen
44956f54b391677d78379729dd14518edddf3c7660Etan Cohen    public static void initHalMockLibrary() throws Exception {
45956f54b391677d78379729dd14518edddf3c7660Etan Cohen        /*
46956f54b391677d78379729dd14518edddf3c7660Etan Cohen         * Setting the Wi-Fi HAL handle and interface (array) to dummy
47956f54b391677d78379729dd14518edddf3c7660Etan Cohen         * values. Required to fake the init checking code to think that
48956f54b391677d78379729dd14518edddf3c7660Etan Cohen         * the HAL actually started.
49956f54b391677d78379729dd14518edddf3c7660Etan Cohen         *
50956f54b391677d78379729dd14518edddf3c7660Etan Cohen         * Note that values are not important since they are only used by
51956f54b391677d78379729dd14518edddf3c7660Etan Cohen         * the real HAL - which is mocked-out in this use-case.
52956f54b391677d78379729dd14518edddf3c7660Etan Cohen         */
53956f54b391677d78379729dd14518edddf3c7660Etan Cohen        Field field = WifiNative.class.getDeclaredField("sWifiHalHandle");
54956f54b391677d78379729dd14518edddf3c7660Etan Cohen        field.setAccessible(true);
55956f54b391677d78379729dd14518edddf3c7660Etan Cohen        long currentWifiHalHandle = field.getLong(null);
56956f54b391677d78379729dd14518edddf3c7660Etan Cohen        if (DBG) Log.d(TAG, "currentWifiHalHandle=" + currentWifiHalHandle);
57956f54b391677d78379729dd14518edddf3c7660Etan Cohen        if (currentWifiHalHandle == 0) {
58956f54b391677d78379729dd14518edddf3c7660Etan Cohen            field.setLong(null, 5);
59956f54b391677d78379729dd14518edddf3c7660Etan Cohen
60956f54b391677d78379729dd14518edddf3c7660Etan Cohen            field = WifiNative.class.getDeclaredField("sWifiIfaceHandles");
61956f54b391677d78379729dd14518edddf3c7660Etan Cohen            field.setAccessible(true);
62956f54b391677d78379729dd14518edddf3c7660Etan Cohen            long[] wifiIfaceHandles = {
63956f54b391677d78379729dd14518edddf3c7660Etan Cohen                    10 };
64956f54b391677d78379729dd14518edddf3c7660Etan Cohen            field.set(null, wifiIfaceHandles);
65956f54b391677d78379729dd14518edddf3c7660Etan Cohen        }
66956f54b391677d78379729dd14518edddf3c7660Etan Cohen
67956f54b391677d78379729dd14518edddf3c7660Etan Cohen        initHalMock();
68956f54b391677d78379729dd14518edddf3c7660Etan Cohen    }
69956f54b391677d78379729dd14518edddf3c7660Etan Cohen
70956f54b391677d78379729dd14518edddf3c7660Etan Cohen    /*
71956f54b391677d78379729dd14518edddf3c7660Etan Cohen     * JSON data-model for passing arguments between mock host (java) and mock
72956f54b391677d78379729dd14518edddf3c7660Etan Cohen     * HAL (C):
73956f54b391677d78379729dd14518edddf3c7660Etan Cohen     * {
74956f54b391677d78379729dd14518edddf3c7660Etan Cohen     *      "name" : { "type" : "int|byte_array", "value" : 123 | [1, 2, 3, 4] }
75956f54b391677d78379729dd14518edddf3c7660Etan Cohen     * }
76956f54b391677d78379729dd14518edddf3c7660Etan Cohen     */
77956f54b391677d78379729dd14518edddf3c7660Etan Cohen
78956f54b391677d78379729dd14518edddf3c7660Etan Cohen    private static final String TYPE_KEY = "type";
79956f54b391677d78379729dd14518edddf3c7660Etan Cohen    private static final String VALUE_KEY = "value";
80956f54b391677d78379729dd14518edddf3c7660Etan Cohen
81956f54b391677d78379729dd14518edddf3c7660Etan Cohen    private static final String TYPE_INT = "int";
82956f54b391677d78379729dd14518edddf3c7660Etan Cohen    private static final String TYPE_BYTE_ARRAY = "byte_array";
83956f54b391677d78379729dd14518edddf3c7660Etan Cohen
84956f54b391677d78379729dd14518edddf3c7660Etan Cohen    public static Bundle convertJsonToBundle(String jsonArgs) throws JSONException {
85956f54b391677d78379729dd14518edddf3c7660Etan Cohen        if (VDBG) Log.v(TAG, "convertJsonToBundle: jsonArgs=" + jsonArgs);
86956f54b391677d78379729dd14518edddf3c7660Etan Cohen
87956f54b391677d78379729dd14518edddf3c7660Etan Cohen        Bundle bundle = new Bundle();
88956f54b391677d78379729dd14518edddf3c7660Etan Cohen
89956f54b391677d78379729dd14518edddf3c7660Etan Cohen        JSONObject jsonObject = new JSONObject(jsonArgs);
90956f54b391677d78379729dd14518edddf3c7660Etan Cohen        Iterator<String> iter = jsonObject.keys();
91956f54b391677d78379729dd14518edddf3c7660Etan Cohen        while (iter.hasNext()) {
92956f54b391677d78379729dd14518edddf3c7660Etan Cohen            String key = iter.next();
93956f54b391677d78379729dd14518edddf3c7660Etan Cohen            JSONObject field = jsonObject.optJSONObject(key);
94956f54b391677d78379729dd14518edddf3c7660Etan Cohen
95956f54b391677d78379729dd14518edddf3c7660Etan Cohen            String type = field.getString(TYPE_KEY);
96956f54b391677d78379729dd14518edddf3c7660Etan Cohen
97956f54b391677d78379729dd14518edddf3c7660Etan Cohen            if (TYPE_INT.equals(type)) {
98956f54b391677d78379729dd14518edddf3c7660Etan Cohen                bundle.putInt(key, field.optInt(VALUE_KEY));
99956f54b391677d78379729dd14518edddf3c7660Etan Cohen            } else if (TYPE_BYTE_ARRAY.equals(type)) {
100956f54b391677d78379729dd14518edddf3c7660Etan Cohen                JSONArray array = field.optJSONArray(VALUE_KEY);
101956f54b391677d78379729dd14518edddf3c7660Etan Cohen                byte[] bArray = new byte[array.length()];
102956f54b391677d78379729dd14518edddf3c7660Etan Cohen                for (int i = 0; i < array.length(); ++i) {
103956f54b391677d78379729dd14518edddf3c7660Etan Cohen                    bArray[i] = (byte) array.getInt(i);
104956f54b391677d78379729dd14518edddf3c7660Etan Cohen                }
105956f54b391677d78379729dd14518edddf3c7660Etan Cohen                bundle.putByteArray(key, bArray);
106956f54b391677d78379729dd14518edddf3c7660Etan Cohen            } else {
107956f54b391677d78379729dd14518edddf3c7660Etan Cohen                throw new JSONException("Unexpected TYPE read from mock HAL -- '" + type + "'");
108956f54b391677d78379729dd14518edddf3c7660Etan Cohen            }
109956f54b391677d78379729dd14518edddf3c7660Etan Cohen        }
110956f54b391677d78379729dd14518edddf3c7660Etan Cohen
111956f54b391677d78379729dd14518edddf3c7660Etan Cohen        if (DBG) Log.d(TAG, "convertJsonToBundle: returning bundle=" + bundle);
112956f54b391677d78379729dd14518edddf3c7660Etan Cohen        return bundle;
113956f54b391677d78379729dd14518edddf3c7660Etan Cohen    }
114956f54b391677d78379729dd14518edddf3c7660Etan Cohen
115956f54b391677d78379729dd14518edddf3c7660Etan Cohen    public static JSONObject convertBundleToJson(Bundle bundle) throws JSONException {
116956f54b391677d78379729dd14518edddf3c7660Etan Cohen        if (VDBG) Log.v(TAG, "convertBundleToJson: bundle=" + bundle.toString());
117956f54b391677d78379729dd14518edddf3c7660Etan Cohen
118956f54b391677d78379729dd14518edddf3c7660Etan Cohen        JSONObject json = new JSONObject();
119956f54b391677d78379729dd14518edddf3c7660Etan Cohen        for (String key : bundle.keySet()) {
120956f54b391677d78379729dd14518edddf3c7660Etan Cohen            Object value = bundle.get(key);
121956f54b391677d78379729dd14518edddf3c7660Etan Cohen            JSONObject child = new JSONObject();
122956f54b391677d78379729dd14518edddf3c7660Etan Cohen            if (value instanceof Integer) {
123956f54b391677d78379729dd14518edddf3c7660Etan Cohen                child.put(TYPE_KEY, TYPE_INT);
124956f54b391677d78379729dd14518edddf3c7660Etan Cohen                child.put(VALUE_KEY, ((Integer) value).intValue());
125956f54b391677d78379729dd14518edddf3c7660Etan Cohen            } else if (value instanceof byte[]) {
126956f54b391677d78379729dd14518edddf3c7660Etan Cohen                byte[] array = (byte[]) value;
127956f54b391677d78379729dd14518edddf3c7660Etan Cohen                JSONArray jsonArray = new JSONArray();
128956f54b391677d78379729dd14518edddf3c7660Etan Cohen                for (int i = 0; i < array.length; ++i) {
129956f54b391677d78379729dd14518edddf3c7660Etan Cohen                    jsonArray.put(array[i]);
130956f54b391677d78379729dd14518edddf3c7660Etan Cohen                }
131956f54b391677d78379729dd14518edddf3c7660Etan Cohen                child.put(TYPE_KEY, TYPE_BYTE_ARRAY);
132956f54b391677d78379729dd14518edddf3c7660Etan Cohen                child.put(VALUE_KEY, jsonArray);
133956f54b391677d78379729dd14518edddf3c7660Etan Cohen            } else {
134956f54b391677d78379729dd14518edddf3c7660Etan Cohen                throw new JSONException("Unexpected type of JSON tree node (not an Integer "
135956f54b391677d78379729dd14518edddf3c7660Etan Cohen                        + "or byte[]): " + value);
136956f54b391677d78379729dd14518edddf3c7660Etan Cohen            }
137956f54b391677d78379729dd14518edddf3c7660Etan Cohen            json.put(key, child);
138956f54b391677d78379729dd14518edddf3c7660Etan Cohen        }
139956f54b391677d78379729dd14518edddf3c7660Etan Cohen
140956f54b391677d78379729dd14518edddf3c7660Etan Cohen        if (DBG) Log.d(TAG, "convertBundleToJson: returning JSONObject=" + json);
141956f54b391677d78379729dd14518edddf3c7660Etan Cohen        return json;
142956f54b391677d78379729dd14518edddf3c7660Etan Cohen    }
143956f54b391677d78379729dd14518edddf3c7660Etan Cohen}
144