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