XmlUtil.java revision 06a2281303248446bacc87a00ab66ea1fdf0392d
12b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius/* 22b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Copyright (C) 2016 The Android Open Source Project 32b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 42b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Licensed under the Apache License, Version 2.0 (the "License"); 52b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * you may not use this file except in compliance with the License. 62b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * You may obtain a copy of the License at 72b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 82b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * http://www.apache.org/licenses/LICENSE-2.0 92b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 102b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Unless required by applicable law or agreed to in writing, software 112b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * distributed under the License is distributed on an "AS IS" BASIS, 122b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * See the License for the specific language governing permissions and 142b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * limitations under the License. 152b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 162b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 172b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Piuspackage com.android.server.wifi.util; 182b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 19e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.IpConfiguration; 20e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.IpConfiguration.IpAssignment; 21e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.IpConfiguration.ProxySettings; 22e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.LinkAddress; 23e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.NetworkUtils; 24e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.ProxyInfo; 25e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.RouteInfo; 26e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.StaticIpConfiguration; 27e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.net.wifi.WifiConfiguration; 28e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport android.util.Log; 29e33a4bb414892435c016486585c26022cafdab68Roshan Pius 302b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Piusimport com.android.internal.util.XmlUtils; 312b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 322b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Piusimport org.xmlpull.v1.XmlPullParser; 332b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Piusimport org.xmlpull.v1.XmlPullParserException; 342b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Piusimport org.xmlpull.v1.XmlSerializer; 352b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 362b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Piusimport java.io.IOException; 37e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport java.net.Inet4Address; 38e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport java.net.InetAddress; 39e33a4bb414892435c016486585c26022cafdab68Roshan Piusimport java.util.BitSet; 402b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 412b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius/** 422b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Utils for manipulating XML data. This is essentially a wrapper over XmlUtils provided by core. 432b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * The utility provides methods to write/parse section headers and write/parse values. 442b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * This utility is designed for formatting the XML into the following format: 452b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * <Document Header> 462b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * <Section 1 Header> 472b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * <Value 1> 482b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * <Value 2> 492b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * ... 502b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * <Sub Section 1 Header> 512b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * <Value 1> 522b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * <Value 2> 532b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * ... 542b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * </Sub Section 1 Header> 552b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * </Section 1 Header> 562b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * </Document Header> 572b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 582b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Piuspublic class XmlUtil { 592b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius private static final String TAG = "WifiXmlUtil"; 602b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 612b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 62e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Ensure that the XML stream is at a start tag or the end of document. 63e33a4bb414892435c016486585c26022cafdab68Roshan Pius * 64052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius * @throws XmlPullParserException if parsing errors occur. 652b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 66e33a4bb414892435c016486585c26022cafdab68Roshan Pius private static void gotoStartTag(XmlPullParser in) 672b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius throws XmlPullParserException, IOException { 68e33a4bb414892435c016486585c26022cafdab68Roshan Pius int type = in.getEventType(); 69e33a4bb414892435c016486585c26022cafdab68Roshan Pius while (type != XmlPullParser.START_TAG && type != XmlPullParser.END_DOCUMENT) { 70e33a4bb414892435c016486585c26022cafdab68Roshan Pius type = in.next(); 71e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 72e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 73e33a4bb414892435c016486585c26022cafdab68Roshan Pius 74e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 75e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Ensure that the XML stream is at an end tag or the end of document. 76e33a4bb414892435c016486585c26022cafdab68Roshan Pius * 77052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius * @throws XmlPullParserException if parsing errors occur. 78e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 79e33a4bb414892435c016486585c26022cafdab68Roshan Pius private static void gotoEndTag(XmlPullParser in) 80e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 81e33a4bb414892435c016486585c26022cafdab68Roshan Pius int type = in.getEventType(); 82e33a4bb414892435c016486585c26022cafdab68Roshan Pius while (type != XmlPullParser.END_TAG && type != XmlPullParser.END_DOCUMENT) { 83e33a4bb414892435c016486585c26022cafdab68Roshan Pius type = in.next(); 84e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 852b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 862b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 872b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 882b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Start processing the XML stream at the document header. 892b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 902b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param in XmlPullParser instance pointing to the XML stream. 912b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param headerName expected name for the start tag. 92052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius * @throws XmlPullParserException if parsing errors occur. 932b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 942b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius public static void gotoDocumentStart(XmlPullParser in, String headerName) 952b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius throws XmlPullParserException, IOException { 962b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius XmlUtils.beginDocument(in, headerName); 972b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 982b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 992b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 100e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Move the XML stream to the next section header. The provided outerDepth is used to find 101e33a4bb414892435c016486585c26022cafdab68Roshan Pius * sub sections within that depth. 1022b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 1032b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param in XmlPullParser instance pointing to the XML stream. 1042b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param headerName expected name for the start tag. 1052b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param outerDepth Find section within this depth. 1062b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @return {@code true} if a start tag with the provided name is found, {@code false} otherwise 107052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius * @throws XmlPullParserException if parsing errors occur. 1082b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 1092b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius public static boolean gotoNextSection(XmlPullParser in, String headerName, int outerDepth) 1102b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius throws XmlPullParserException, IOException { 1112b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius while (XmlUtils.nextElementWithin(in, outerDepth)) { 1122b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius if (in.getName().equals(headerName)) { 1132b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius return true; 1142b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 1152b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 1162b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius return false; 1172b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 1182b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 1192b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 120e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Checks if the stream is at the end of a section of values. This moves the stream to next tag 121e33a4bb414892435c016486585c26022cafdab68Roshan Pius * and checks if it finds an end tag at the specified depth. 122e33a4bb414892435c016486585c26022cafdab68Roshan Pius * 123e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param in XmlPullParser instance pointing to the XML stream. 124e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param sectionDepth depth of the start tag of this section. Used to match the end tag. 125e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @return {@code true} if a end tag at the provided depth is found, {@code false} otherwise 126052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius * @throws XmlPullParserException if parsing errors occur. 127e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 128e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static boolean isNextSectionEnd(XmlPullParser in, int sectionDepth) 129e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 130052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius return (in.nextTag() == XmlPullParser.END_TAG && in.getDepth() == sectionDepth); 131e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 132e33a4bb414892435c016486585c26022cafdab68Roshan Pius 133e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 134e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Read the current value in the XML stream using core XmlUtils and stores the retrieved 135e33a4bb414892435c016486585c26022cafdab68Roshan Pius * value name in the string provided. This method reads the value contained in current start 136e33a4bb414892435c016486585c26022cafdab68Roshan Pius * tag. 137e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Note: Because there could be genuine null values being read from the XML, this method raises 138e33a4bb414892435c016486585c26022cafdab68Roshan Pius * an exception to indicate errors. 139e33a4bb414892435c016486585c26022cafdab68Roshan Pius * 140e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param in XmlPullParser instance pointing to the XML stream. 141e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param valueName An array of one string, used to return the name attribute 142e33a4bb414892435c016486585c26022cafdab68Roshan Pius * of the value's tag. 143e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @return value retrieved from the XML stream. 144052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius * @throws XmlPullParserException if parsing errors occur. 145e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 146e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static Object readCurrentValue(XmlPullParser in, String[] valueName) 147e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 148e33a4bb414892435c016486585c26022cafdab68Roshan Pius Object value = XmlUtils.readValueXml(in, valueName); 149e33a4bb414892435c016486585c26022cafdab68Roshan Pius // XmlUtils.readValue does not always move the stream to the end of the tag. So, move 150e33a4bb414892435c016486585c26022cafdab68Roshan Pius // it to the end tag before returning from here. 151e33a4bb414892435c016486585c26022cafdab68Roshan Pius gotoEndTag(in); 152e33a4bb414892435c016486585c26022cafdab68Roshan Pius return value; 153e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 154e33a4bb414892435c016486585c26022cafdab68Roshan Pius 155e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 1562b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Read the next value in the XML stream using core XmlUtils and ensure that it matches the 157e33a4bb414892435c016486585c26022cafdab68Roshan Pius * provided name. This method moves the stream to the next start tag and reads the value 158e33a4bb414892435c016486585c26022cafdab68Roshan Pius * contained in it. 1592b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Note: Because there could be genuine null values being read from the XML, this method raises 1602b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * an exception to indicate errors. 1612b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 1622b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param in XmlPullParser instance pointing to the XML stream. 1632b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @return value retrieved from the XML stream. 164052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius * @throws XmlPullParserException if the value read does not match |expectedName|, 165052b948a8b8a009486e35cb56dbd7bb9516e8626Roshan Pius * or if parsing errors occur. 1662b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 167e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static Object readNextValueWithName(XmlPullParser in, String expectedName) 1682b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius throws XmlPullParserException, IOException { 169e33a4bb414892435c016486585c26022cafdab68Roshan Pius String[] valueName = new String[1]; 170e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtils.nextElement(in); 171e33a4bb414892435c016486585c26022cafdab68Roshan Pius Object value = readCurrentValue(in, valueName); 172e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (valueName[0].equals(expectedName)) { 1732b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius return value; 1742b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 1752b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius throw new XmlPullParserException( 176e33a4bb414892435c016486585c26022cafdab68Roshan Pius "Value not found. Expected: " + expectedName + ", but got: " + valueName[0]); 1772b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 1782b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 1792b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 1802b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Write the XML document start with the provided document header name. 1812b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 1822b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param out XmlSerializer instance pointing to the XML stream. 1832b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param headerName name for the start tag. 1842b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 1852b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius public static void writeDocumentStart(XmlSerializer out, String headerName) 186e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws IOException { 1872b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius out.startDocument(null, true); 1882b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius out.startTag(null, headerName); 1892b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 1902b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 1912b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 1922b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Write the XML document end with the provided document header name. 1932b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 1942b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param out XmlSerializer instance pointing to the XML stream. 1952b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param headerName name for the end tag. 1962b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 1972b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius public static void writeDocumentEnd(XmlSerializer out, String headerName) 198e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws IOException { 1992b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius out.endTag(null, headerName); 2002b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius out.endDocument(); 2012b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 2022b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 2032b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 2042b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Write a section start header tag with the provided section name. 2052b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 2062b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param out XmlSerializer instance pointing to the XML stream. 2072b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param headerName name for the start tag. 2082b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 2092b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius public static void writeNextSectionStart(XmlSerializer out, String headerName) 210e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws IOException { 2112b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius out.startTag(null, headerName); 2122b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 2132b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 2142b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 2152b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Write a section end header tag with the provided section name. 2162b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 2172b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param out XmlSerializer instance pointing to the XML stream. 2182b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param headerName name for the end tag. 2192b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 2202b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius public static void writeNextSectionEnd(XmlSerializer out, String headerName) 221e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws IOException { 2222b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius out.endTag(null, headerName); 2232b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 2242b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 2252b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius /** 2262b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * Write the value with the provided name in the XML stream using core XmlUtils. 2272b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * 2282b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param out XmlSerializer instance pointing to the XML stream. 2292b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param name name of the value. 2302b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius * @param value value to be written. 2312b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius */ 2322b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius public static void writeNextValue(XmlSerializer out, String name, Object value) 2332b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius throws XmlPullParserException, IOException { 2342b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius XmlUtils.writeValueXml(value, name, out); 2352b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius } 236e33a4bb414892435c016486585c26022cafdab68Roshan Pius 237e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 238e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Utility class to serialize and deseriaize WifConfiguration object to XML & vice versa. 239e33a4bb414892435c016486585c26022cafdab68Roshan Pius * This is used by both #com.android.server.wifi.WifiConfigStore & 240e33a4bb414892435c016486585c26022cafdab68Roshan Pius * #com.android.server.wifi.WifiBackupRestore modules. 241e33a4bb414892435c016486585c26022cafdab68Roshan Pius * The |writeConfigurationToXml| has 2 versions, one for backup and one for config store. 242e33a4bb414892435c016486585c26022cafdab68Roshan Pius * There is only 1 version of |parseXmlToConfiguration| for both backup & config store. 243e33a4bb414892435c016486585c26022cafdab68Roshan Pius * The parse method is written so that any element added/deleted in future revisions can 244e33a4bb414892435c016486585c26022cafdab68Roshan Pius * be easily handled. 245e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 246e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static class WifiConfigurationXmlUtil { 247e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 248e33a4bb414892435c016486585c26022cafdab68Roshan Pius * List of XML tags corresponding to WifiConfiguration object elements. 249e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 250e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_SSID = "SSID"; 251e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_BSSID = "BSSID"; 252e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_CONFIG_KEY = "ConfigKey"; 253e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_PRE_SHARED_KEY = "PreSharedKey"; 254e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_WEP_KEYS = "WEPKeys"; 255e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_WEP_TX_KEY_INDEX = "WEPTxKeyIndex"; 256e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_HIDDEN_SSID = "HiddenSSID"; 257e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_ALLOWED_KEY_MGMT = "AllowedKeyMgmt"; 258e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_ALLOWED_PROTOCOLS = "AllowedProtocols"; 259e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_ALLOWED_AUTH_ALGOS = "AllowedAuthAlgos"; 260e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_SHARED = "Shared"; 261e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_CREATOR_UID = "CreatorUid"; 262e33a4bb414892435c016486585c26022cafdab68Roshan Pius 263e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 264e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Write WepKeys to the XML stream. 265e33a4bb414892435c016486585c26022cafdab68Roshan Pius * WepKeys array is intialized in WifiConfiguration constructor, but all of the elements 26606a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius * are set to null. User may chose to set any one of the key elements in WifiConfiguration. 26706a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius * XmlUtils serialization doesn't handle this array of nulls well . 26806a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius * So, write empty strings if some of the keys are not initialized and null if all of 26906a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius * the elements are empty. 270e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 271e33a4bb414892435c016486585c26022cafdab68Roshan Pius private static void writeWepKeysToXml(XmlSerializer out, String[] wepKeys) 272e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 27306a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius String[] wepKeysToWrite = new String[wepKeys.length]; 27406a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius boolean hasWepKey = false; 27506a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius for (int i = 0; i < wepKeys.length; i++) { 27606a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius if (wepKeys[i] == null) { 27706a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius wepKeysToWrite[i] = new String(); 27806a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius } else { 27906a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius wepKeysToWrite[i] = wepKeys[i]; 28006a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius hasWepKey = true; 28106a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius } 28206a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius } 28306a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius if (hasWepKey) { 28406a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, wepKeysToWrite); 285e33a4bb414892435c016486585c26022cafdab68Roshan Pius } else { 286e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_WEP_KEYS, null); 287e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 288e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 289e33a4bb414892435c016486585c26022cafdab68Roshan Pius 290e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 291e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Write the Configuration data elements that are common for backup & config store to the 292e33a4bb414892435c016486585c26022cafdab68Roshan Pius * XML stream. 293e33a4bb414892435c016486585c26022cafdab68Roshan Pius * 294e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param out XmlSerializer instance pointing to the XML stream. 295e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param configuration WifiConfiguration object to be serialized. 296e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 297e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static void writeCommonWifiConfigurationElementsToXml(XmlSerializer out, 298e33a4bb414892435c016486585c26022cafdab68Roshan Pius WifiConfiguration configuration) 299e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 300e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_CONFIG_KEY, configuration.configKey()); 301e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_SSID, configuration.SSID); 302e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_BSSID, configuration.BSSID); 303e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_PRE_SHARED_KEY, configuration.preSharedKey); 304e33a4bb414892435c016486585c26022cafdab68Roshan Pius writeWepKeysToXml(out, configuration.wepKeys); 305e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_WEP_TX_KEY_INDEX, configuration.wepTxKeyIndex); 306e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_HIDDEN_SSID, configuration.hiddenSSID); 307e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 308e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_ALLOWED_KEY_MGMT, 309e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.allowedKeyManagement.toByteArray()); 310e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 311e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_ALLOWED_PROTOCOLS, 312e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.allowedProtocols.toByteArray()); 313e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 314e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_ALLOWED_AUTH_ALGOS, 315e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.allowedAuthAlgorithms.toByteArray()); 316e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_SHARED, configuration.shared); 317e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_CREATOR_UID, configuration.creatorUid); 318e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 319e33a4bb414892435c016486585c26022cafdab68Roshan Pius 320e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 321e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Write the Configuration data elements for backup from the provided Configuration to the 322e33a4bb414892435c016486585c26022cafdab68Roshan Pius * XML stream. 323e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Note: This is a subset of the elements serialized for config store. 324e33a4bb414892435c016486585c26022cafdab68Roshan Pius * 325e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param out XmlSerializer instance pointing to the XML stream. 326e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param configuration WifiConfiguration object to be serialized. 327e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 328e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static void writeWifiConfigurationToXmlForBackup(XmlSerializer out, 329e33a4bb414892435c016486585c26022cafdab68Roshan Pius WifiConfiguration configuration) 330e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 331e33a4bb414892435c016486585c26022cafdab68Roshan Pius writeCommonWifiConfigurationElementsToXml(out, configuration); 332e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 333e33a4bb414892435c016486585c26022cafdab68Roshan Pius 334e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 335e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Write the Configuration data elements for config store from the provided Configuration 336e33a4bb414892435c016486585c26022cafdab68Roshan Pius * to the XML stream. 337e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 338e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static void writeWifiConfigurationToXmlForConfigStore(XmlSerializer out, 339e33a4bb414892435c016486585c26022cafdab68Roshan Pius WifiConfiguration configuration) 340e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 341e33a4bb414892435c016486585c26022cafdab68Roshan Pius writeCommonWifiConfigurationElementsToXml(out, configuration); 342e33a4bb414892435c016486585c26022cafdab68Roshan Pius // TODO: Will need to add more elements which needs to be persisted. 343e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 344e33a4bb414892435c016486585c26022cafdab68Roshan Pius 345e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 34606a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius * Populate wepKeys array elements only if they were non-empty in the backup data. 34706a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius * @throws XmlPullParserException if parsing errors occur. 348e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 349e33a4bb414892435c016486585c26022cafdab68Roshan Pius private static void populateWepKeysFromXmlValue(Object value, String[] wepKeys) 350e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 351e33a4bb414892435c016486585c26022cafdab68Roshan Pius String[] wepKeysInData = (String[]) value; 35206a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius if (wepKeysInData == null) { 35306a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius return; 35406a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius } 35506a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius if (wepKeysInData.length != wepKeys.length) { 35606a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius throw new XmlPullParserException( 35706a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius "Invalid Wep Keys length: " + wepKeysInData.length); 35806a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius } 35906a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius for (int i = 0; i < wepKeys.length; i++) { 36006a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius if (wepKeysInData[i].isEmpty()) { 36106a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius wepKeys[i] = null; 36206a2281303248446bacc87a00ab66ea1fdf0392dRoshan Pius } else { 363e33a4bb414892435c016486585c26022cafdab68Roshan Pius wepKeys[i] = wepKeysInData[i]; 364e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 365e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 366e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 367e33a4bb414892435c016486585c26022cafdab68Roshan Pius 368e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 369e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Parses the configuration data elements from the provided XML stream to a Configuration. 370e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Note: This is used for parsing both backup data and config store data. Looping through 371e33a4bb414892435c016486585c26022cafdab68Roshan Pius * the tags make it easy to add or remove elements in the future versions if needed. 372e33a4bb414892435c016486585c26022cafdab68Roshan Pius * 373e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param in XmlPullParser instance pointing to the XML stream. 374e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param outerTagDepth depth of the outer tag in the XML document. 375e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @return WifiConfiguration object if parsing is successful, null otherwise. 376e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 377e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static WifiConfiguration parseWifiConfigurationFromXml(XmlPullParser in, 378e33a4bb414892435c016486585c26022cafdab68Roshan Pius int outerTagDepth) 379e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 380e33a4bb414892435c016486585c26022cafdab68Roshan Pius WifiConfiguration configuration = new WifiConfiguration(); 381e33a4bb414892435c016486585c26022cafdab68Roshan Pius String configKeyInData = null; 382e33a4bb414892435c016486585c26022cafdab68Roshan Pius 383e33a4bb414892435c016486585c26022cafdab68Roshan Pius // Loop through and parse out all the elements from the stream within this section. 384e33a4bb414892435c016486585c26022cafdab68Roshan Pius while (!XmlUtil.isNextSectionEnd(in, outerTagDepth)) { 385e33a4bb414892435c016486585c26022cafdab68Roshan Pius String[] valueName = new String[1]; 386e33a4bb414892435c016486585c26022cafdab68Roshan Pius Object value = XmlUtil.readCurrentValue(in, valueName); 387e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (valueName[0] == null) { 388e33a4bb414892435c016486585c26022cafdab68Roshan Pius Log.e(TAG, "Missing value name"); 389e33a4bb414892435c016486585c26022cafdab68Roshan Pius return null; 390e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 391e33a4bb414892435c016486585c26022cafdab68Roshan Pius switch (valueName[0]) { 392e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_CONFIG_KEY: 393e33a4bb414892435c016486585c26022cafdab68Roshan Pius configKeyInData = (String) value; 394e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 395e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_SSID: 396e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.SSID = (String) value; 397e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 398e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_BSSID: 399e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.BSSID = (String) value; 400e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 401e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_PRE_SHARED_KEY: 402e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.preSharedKey = (String) value; 403e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 404e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_WEP_KEYS: 405e33a4bb414892435c016486585c26022cafdab68Roshan Pius populateWepKeysFromXmlValue(value, configuration.wepKeys); 406e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 407e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_WEP_TX_KEY_INDEX: 408e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.wepTxKeyIndex = (int) value; 409e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 410e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_HIDDEN_SSID: 411e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.hiddenSSID = (boolean) value; 412e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 413e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_ALLOWED_KEY_MGMT: 414e33a4bb414892435c016486585c26022cafdab68Roshan Pius byte[] allowedKeyMgmt = (byte[]) value; 415e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.allowedKeyManagement = BitSet.valueOf(allowedKeyMgmt); 416e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 417e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_ALLOWED_PROTOCOLS: 418e33a4bb414892435c016486585c26022cafdab68Roshan Pius byte[] allowedProtocols = (byte[]) value; 419e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.allowedProtocols = BitSet.valueOf(allowedProtocols); 420e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 421e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_ALLOWED_AUTH_ALGOS: 422e33a4bb414892435c016486585c26022cafdab68Roshan Pius byte[] allowedAuthAlgorithms = (byte[]) value; 423e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.allowedAuthAlgorithms = BitSet.valueOf(allowedAuthAlgorithms); 424e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 425e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_SHARED: 426e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.shared = (boolean) value; 427e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 428e33a4bb414892435c016486585c26022cafdab68Roshan Pius case XML_TAG_CREATOR_UID: 429e33a4bb414892435c016486585c26022cafdab68Roshan Pius configuration.creatorUid = (int) value; 430e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 431e33a4bb414892435c016486585c26022cafdab68Roshan Pius default: 432e33a4bb414892435c016486585c26022cafdab68Roshan Pius Log.e(TAG, "Unknown value name found: " + valueName[0]); 433e33a4bb414892435c016486585c26022cafdab68Roshan Pius return null; 434e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 435e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 436e33a4bb414892435c016486585c26022cafdab68Roshan Pius // We should now have all the data to calculate the configKey. Compare it against the 437e33a4bb414892435c016486585c26022cafdab68Roshan Pius // configKey stored in the XML data. 438e33a4bb414892435c016486585c26022cafdab68Roshan Pius String configKeyCalculated = configuration.configKey(); 439e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (configKeyInData == null || !configKeyInData.equals(configKeyCalculated)) { 440e33a4bb414892435c016486585c26022cafdab68Roshan Pius Log.e(TAG, "Configuration key does not match. Retrieved: " + configKeyInData 441e33a4bb414892435c016486585c26022cafdab68Roshan Pius + ", Calculated: " + configKeyCalculated); 442e33a4bb414892435c016486585c26022cafdab68Roshan Pius return null; 443e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 444e33a4bb414892435c016486585c26022cafdab68Roshan Pius return configuration; 445e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 446e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 447e33a4bb414892435c016486585c26022cafdab68Roshan Pius 448e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 449e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Utility class to serialize and deseriaize IpConfiguration object to XML & vice versa. 450e33a4bb414892435c016486585c26022cafdab68Roshan Pius * This is used by both #com.android.server.wifi.WifiConfigStore & 451e33a4bb414892435c016486585c26022cafdab68Roshan Pius * #com.android.server.wifi.WifiBackupRestore modules. 452e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 453e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static class IpConfigurationXmlUtil { 454e33a4bb414892435c016486585c26022cafdab68Roshan Pius 455e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 456e33a4bb414892435c016486585c26022cafdab68Roshan Pius * List of XML tags corresponding to IpConfiguration object elements. 457e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 458e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_IP_ASSIGNMENT = "IpAssignment"; 459e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_LINK_ADDRESS = "LinkAddress"; 460e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_LINK_PREFIX_LENGTH = "LinkPrefixLength"; 461e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_GATEWAY_ADDRESS = "GatewayAddress"; 462e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_DNS_SERVER_ADDRESSES = "DNSServers"; 463e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_PROXY_SETTINGS = "ProxySettings"; 464e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_PROXY_HOST = "ProxyHost"; 465e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_PROXY_PORT = "ProxyPort"; 466e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_PROXY_PAC_FILE = "ProxyPac"; 467e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static final String XML_TAG_PROXY_EXCLUSION_LIST = "ProxyExclusionList"; 468e33a4bb414892435c016486585c26022cafdab68Roshan Pius 469e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 470e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Write the static IP configuration data elements to XML stream. 471e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 472e33a4bb414892435c016486585c26022cafdab68Roshan Pius private static void writeStaticIpConfigurationToXml(XmlSerializer out, 473e33a4bb414892435c016486585c26022cafdab68Roshan Pius StaticIpConfiguration staticIpConfiguration) 474e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 475e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (staticIpConfiguration.ipAddress != null) { 476e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 477e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_LINK_ADDRESS, 478e33a4bb414892435c016486585c26022cafdab68Roshan Pius staticIpConfiguration.ipAddress.getAddress().getHostAddress()); 479e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 480e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_LINK_PREFIX_LENGTH, 481e33a4bb414892435c016486585c26022cafdab68Roshan Pius staticIpConfiguration.ipAddress.getPrefixLength()); 482e33a4bb414892435c016486585c26022cafdab68Roshan Pius } else { 483e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 484e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_LINK_ADDRESS, null); 485e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 486e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_LINK_PREFIX_LENGTH, null); 487e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 488e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (staticIpConfiguration.gateway != null) { 489e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 490e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_GATEWAY_ADDRESS, 491e33a4bb414892435c016486585c26022cafdab68Roshan Pius staticIpConfiguration.gateway.getHostAddress()); 492e33a4bb414892435c016486585c26022cafdab68Roshan Pius } else { 493e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 494e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_GATEWAY_ADDRESS, null); 495e33a4bb414892435c016486585c26022cafdab68Roshan Pius 496e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 497e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (staticIpConfiguration.dnsServers != null) { 498e33a4bb414892435c016486585c26022cafdab68Roshan Pius // Create a string array of DNS server addresses 499e33a4bb414892435c016486585c26022cafdab68Roshan Pius String[] dnsServers = new String[staticIpConfiguration.dnsServers.size()]; 500e33a4bb414892435c016486585c26022cafdab68Roshan Pius int dnsServerIdx = 0; 501e33a4bb414892435c016486585c26022cafdab68Roshan Pius for (InetAddress inetAddr : staticIpConfiguration.dnsServers) { 502e33a4bb414892435c016486585c26022cafdab68Roshan Pius dnsServers[dnsServerIdx++] = inetAddr.getHostAddress(); 503e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 504e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 505e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_DNS_SERVER_ADDRESSES, dnsServers); 506e33a4bb414892435c016486585c26022cafdab68Roshan Pius } else { 507e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 508e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_DNS_SERVER_ADDRESSES, null); 509e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 510e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 511e33a4bb414892435c016486585c26022cafdab68Roshan Pius 512e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 513e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Write the IP configuration data elements from the provided Configuration to the XML 514e33a4bb414892435c016486585c26022cafdab68Roshan Pius * stream. 515e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 516e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static void writeIpConfigurationToXml(XmlSerializer out, 517e33a4bb414892435c016486585c26022cafdab68Roshan Pius IpConfiguration ipConfiguration) 518e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 519e33a4bb414892435c016486585c26022cafdab68Roshan Pius // Write IP assignment settings 520e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue(out, XML_TAG_IP_ASSIGNMENT, 521e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.ipAssignment.toString()); 522e33a4bb414892435c016486585c26022cafdab68Roshan Pius switch (ipConfiguration.ipAssignment) { 523e33a4bb414892435c016486585c26022cafdab68Roshan Pius case STATIC: 524e33a4bb414892435c016486585c26022cafdab68Roshan Pius writeStaticIpConfigurationToXml( 525e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, ipConfiguration.getStaticIpConfiguration()); 526e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 527e33a4bb414892435c016486585c26022cafdab68Roshan Pius default: 528e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 529e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 530e33a4bb414892435c016486585c26022cafdab68Roshan Pius 531e33a4bb414892435c016486585c26022cafdab68Roshan Pius // Write proxy settings 532e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 533e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_PROXY_SETTINGS, 534e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.proxySettings.toString()); 535e33a4bb414892435c016486585c26022cafdab68Roshan Pius switch (ipConfiguration.proxySettings) { 536e33a4bb414892435c016486585c26022cafdab68Roshan Pius case STATIC: 537e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 538e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_PROXY_HOST, 539e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.httpProxy.getHost()); 540e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 541e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_PROXY_PORT, 542e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.httpProxy.getPort()); 543e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 544e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_PROXY_EXCLUSION_LIST, 545e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.httpProxy.getExclusionListAsString()); 546e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 547e33a4bb414892435c016486585c26022cafdab68Roshan Pius case PAC: 548e33a4bb414892435c016486585c26022cafdab68Roshan Pius XmlUtil.writeNextValue( 549e33a4bb414892435c016486585c26022cafdab68Roshan Pius out, XML_TAG_PROXY_PAC_FILE, 550e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.httpProxy.getPacFileUrl().toString()); 551e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 552e33a4bb414892435c016486585c26022cafdab68Roshan Pius default: 553e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 554e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 555e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 556e33a4bb414892435c016486585c26022cafdab68Roshan Pius 557e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 558e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Parse out the static IP configuration from the XML stream. 559e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 560e33a4bb414892435c016486585c26022cafdab68Roshan Pius private static StaticIpConfiguration parseStaticIpConfigurationFromXml(XmlPullParser in) 561e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 562e33a4bb414892435c016486585c26022cafdab68Roshan Pius StaticIpConfiguration staticIpConfiguration = new StaticIpConfiguration(); 563e33a4bb414892435c016486585c26022cafdab68Roshan Pius 564e33a4bb414892435c016486585c26022cafdab68Roshan Pius String linkAddressString = 565e33a4bb414892435c016486585c26022cafdab68Roshan Pius (String) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_ADDRESS); 566e33a4bb414892435c016486585c26022cafdab68Roshan Pius Integer linkPrefixLength = 567e33a4bb414892435c016486585c26022cafdab68Roshan Pius (Integer) XmlUtil.readNextValueWithName(in, XML_TAG_LINK_PREFIX_LENGTH); 568e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (linkAddressString != null && linkPrefixLength != null) { 569e33a4bb414892435c016486585c26022cafdab68Roshan Pius LinkAddress linkAddress = new LinkAddress( 570e33a4bb414892435c016486585c26022cafdab68Roshan Pius NetworkUtils.numericToInetAddress(linkAddressString), 571e33a4bb414892435c016486585c26022cafdab68Roshan Pius linkPrefixLength); 572e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (linkAddress.getAddress() instanceof Inet4Address) { 573e33a4bb414892435c016486585c26022cafdab68Roshan Pius staticIpConfiguration.ipAddress = linkAddress; 574e33a4bb414892435c016486585c26022cafdab68Roshan Pius } else { 575e33a4bb414892435c016486585c26022cafdab68Roshan Pius Log.w(TAG, "Non-IPv4 address: " + linkAddress); 576e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 577e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 578e33a4bb414892435c016486585c26022cafdab68Roshan Pius String gatewayAddressString = 579e33a4bb414892435c016486585c26022cafdab68Roshan Pius (String) XmlUtil.readNextValueWithName(in, XML_TAG_GATEWAY_ADDRESS); 580e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (gatewayAddressString != null) { 581e33a4bb414892435c016486585c26022cafdab68Roshan Pius LinkAddress dest = null; 582e33a4bb414892435c016486585c26022cafdab68Roshan Pius InetAddress gateway = 583e33a4bb414892435c016486585c26022cafdab68Roshan Pius NetworkUtils.numericToInetAddress(gatewayAddressString); 584e33a4bb414892435c016486585c26022cafdab68Roshan Pius RouteInfo route = new RouteInfo(dest, gateway); 585e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (route.isIPv4Default()) { 586e33a4bb414892435c016486585c26022cafdab68Roshan Pius staticIpConfiguration.gateway = gateway; 587e33a4bb414892435c016486585c26022cafdab68Roshan Pius } else { 588e33a4bb414892435c016486585c26022cafdab68Roshan Pius Log.w(TAG, "Non-IPv4 default route: " + route); 589e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 590e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 591e33a4bb414892435c016486585c26022cafdab68Roshan Pius String[] dnsServerAddressesString = 592e33a4bb414892435c016486585c26022cafdab68Roshan Pius (String[]) XmlUtil.readNextValueWithName(in, XML_TAG_DNS_SERVER_ADDRESSES); 593e33a4bb414892435c016486585c26022cafdab68Roshan Pius if (dnsServerAddressesString != null) { 594e33a4bb414892435c016486585c26022cafdab68Roshan Pius for (String dnsServerAddressString : dnsServerAddressesString) { 595e33a4bb414892435c016486585c26022cafdab68Roshan Pius InetAddress dnsServerAddress = 596e33a4bb414892435c016486585c26022cafdab68Roshan Pius NetworkUtils.numericToInetAddress(dnsServerAddressString); 597e33a4bb414892435c016486585c26022cafdab68Roshan Pius staticIpConfiguration.dnsServers.add(dnsServerAddress); 598e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 599e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 600e33a4bb414892435c016486585c26022cafdab68Roshan Pius return staticIpConfiguration; 601e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 602e33a4bb414892435c016486585c26022cafdab68Roshan Pius 603e33a4bb414892435c016486585c26022cafdab68Roshan Pius /** 604e33a4bb414892435c016486585c26022cafdab68Roshan Pius * Parses the IP configuration data elements from the provided XML stream to a 605e33a4bb414892435c016486585c26022cafdab68Roshan Pius * IpConfiguration. 606e33a4bb414892435c016486585c26022cafdab68Roshan Pius * 607e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param in XmlPullParser instance pointing to the XML stream. 608e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @param outerTagDepth depth of the outer tag in the XML document. 609e33a4bb414892435c016486585c26022cafdab68Roshan Pius * @return IpConfiguration object if parsing is successful, null otherwise. 610e33a4bb414892435c016486585c26022cafdab68Roshan Pius */ 611e33a4bb414892435c016486585c26022cafdab68Roshan Pius public static IpConfiguration parseIpConfigurationFromXml(XmlPullParser in, 612e33a4bb414892435c016486585c26022cafdab68Roshan Pius int outerTagDepth) 613e33a4bb414892435c016486585c26022cafdab68Roshan Pius throws XmlPullParserException, IOException { 614e33a4bb414892435c016486585c26022cafdab68Roshan Pius IpConfiguration ipConfiguration = new IpConfiguration(); 615e33a4bb414892435c016486585c26022cafdab68Roshan Pius 616e33a4bb414892435c016486585c26022cafdab68Roshan Pius // Parse out the IP assignment info first. 617e33a4bb414892435c016486585c26022cafdab68Roshan Pius String ipAssignmentString = 618e33a4bb414892435c016486585c26022cafdab68Roshan Pius (String) XmlUtil.readNextValueWithName(in, XML_TAG_IP_ASSIGNMENT); 619e33a4bb414892435c016486585c26022cafdab68Roshan Pius IpAssignment ipAssignment = IpAssignment.valueOf(ipAssignmentString); 620e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.setIpAssignment(ipAssignment); 621e33a4bb414892435c016486585c26022cafdab68Roshan Pius switch (ipAssignment) { 622e33a4bb414892435c016486585c26022cafdab68Roshan Pius case STATIC: 623e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.setStaticIpConfiguration(parseStaticIpConfigurationFromXml(in)); 624e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 625e33a4bb414892435c016486585c26022cafdab68Roshan Pius case DHCP: 626e33a4bb414892435c016486585c26022cafdab68Roshan Pius case UNASSIGNED: 627e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 628e33a4bb414892435c016486585c26022cafdab68Roshan Pius default: 629e33a4bb414892435c016486585c26022cafdab68Roshan Pius Log.wtf(TAG, "Unknown ip assignment type: " + ipAssignment); 630e33a4bb414892435c016486585c26022cafdab68Roshan Pius return null; 631e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 632e33a4bb414892435c016486585c26022cafdab68Roshan Pius 633e33a4bb414892435c016486585c26022cafdab68Roshan Pius // Parse out the proxy settings next. 634e33a4bb414892435c016486585c26022cafdab68Roshan Pius String proxySettingsString = 635e33a4bb414892435c016486585c26022cafdab68Roshan Pius (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_SETTINGS); 636e33a4bb414892435c016486585c26022cafdab68Roshan Pius ProxySettings proxySettings = ProxySettings.valueOf(proxySettingsString); 637e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.setProxySettings(proxySettings); 638e33a4bb414892435c016486585c26022cafdab68Roshan Pius switch (proxySettings) { 639e33a4bb414892435c016486585c26022cafdab68Roshan Pius case STATIC: 640e33a4bb414892435c016486585c26022cafdab68Roshan Pius String proxyHost = 641e33a4bb414892435c016486585c26022cafdab68Roshan Pius (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_HOST); 642e33a4bb414892435c016486585c26022cafdab68Roshan Pius int proxyPort = 643e33a4bb414892435c016486585c26022cafdab68Roshan Pius (int) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PORT); 644e33a4bb414892435c016486585c26022cafdab68Roshan Pius String proxyExclusionList = 645e33a4bb414892435c016486585c26022cafdab68Roshan Pius (String) XmlUtil.readNextValueWithName( 646e33a4bb414892435c016486585c26022cafdab68Roshan Pius in, XML_TAG_PROXY_EXCLUSION_LIST); 647e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.setHttpProxy( 648e33a4bb414892435c016486585c26022cafdab68Roshan Pius new ProxyInfo(proxyHost, proxyPort, proxyExclusionList)); 649e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 650e33a4bb414892435c016486585c26022cafdab68Roshan Pius case PAC: 651e33a4bb414892435c016486585c26022cafdab68Roshan Pius String proxyPacFile = 652e33a4bb414892435c016486585c26022cafdab68Roshan Pius (String) XmlUtil.readNextValueWithName(in, XML_TAG_PROXY_PAC_FILE); 653e33a4bb414892435c016486585c26022cafdab68Roshan Pius ipConfiguration.setHttpProxy(new ProxyInfo(proxyPacFile)); 654e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 655e33a4bb414892435c016486585c26022cafdab68Roshan Pius case NONE: 656e33a4bb414892435c016486585c26022cafdab68Roshan Pius case UNASSIGNED: 657e33a4bb414892435c016486585c26022cafdab68Roshan Pius break; 658e33a4bb414892435c016486585c26022cafdab68Roshan Pius default: 659e33a4bb414892435c016486585c26022cafdab68Roshan Pius Log.wtf(TAG, "Unknown proxy settings type: " + proxySettings); 660e33a4bb414892435c016486585c26022cafdab68Roshan Pius return null; 661e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 662e33a4bb414892435c016486585c26022cafdab68Roshan Pius return ipConfiguration; 663e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 664e33a4bb414892435c016486585c26022cafdab68Roshan Pius } 6652b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius} 6662b7e486db94455a4a4c0124b5ba5e57c837ef10eRoshan Pius 667