1 /* 2 * Copyright (C) 2017 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.hotspot2.anqp; 18 19 import android.net.Uri; 20 21 import java.io.ByteArrayOutputStream; 22 import java.io.IOException; 23 import java.nio.charset.StandardCharsets; 24 import java.util.Arrays; 25 import java.util.List; 26 import java.util.Locale; 27 28 /** 29 * Utility class containing test data and object for {@link OsuProviderInfo}. 30 */ 31 public class OsuProviderInfoTestUtil { 32 // Test data 33 private static final List<I18Name> TEST_FRIENDLY_NAMES = 34 Arrays.asList(new I18Name("en", Locale.forLanguageTag("en"), "FriendlyName")); 35 private static final String TEST_SERVER_URI = "https://test.server.com"; 36 private static final List<Integer> TEST_METHOD_LIST = Arrays.asList(0, 1); 37 private static final List<IconInfo> TEST_ICON_INFO_LIST = 38 Arrays.asList(IconInfoTestUtil.TEST_ICON_INFO); 39 private static final String TEST_NAI = "network_access@test.com"; 40 private static final List<I18Name> TEST_SERVICE_DESCRIPTIONS = 41 Arrays.asList(new I18Name("en", Locale.forLanguageTag("en"), "Test Service")); 42 43 /** 44 * {@link IconInfo} object with pre-defined test data. 45 */ 46 public static final OsuProviderInfo TEST_OSU_PROVIDER_INFO = 47 new OsuProviderInfo(TEST_FRIENDLY_NAMES, Uri.parse(TEST_SERVER_URI), TEST_METHOD_LIST, 48 TEST_ICON_INFO_LIST, TEST_NAI, TEST_SERVICE_DESCRIPTIONS); 49 50 /** 51 * Raw bytes of icon info with pre-defined test data. 52 */ 53 public static final byte[] TEST_OSU_PROVIDER_INFO_RAW_BYTES = getTestData(); 54 55 public static final byte[] TEST_OSU_PROVIDER_INFO_RAW_BYTES_WITH_INVALID_LENGTH = 56 getTestDataWithInvalidLength(); 57 58 /** 59 * Generate and return the raw data based on pre-defined test data. 60 * 61 * @return byte[] 62 */ getTestData()63 private static byte[] getTestData() { 64 try { 65 ByteArrayOutputStream out = new ByteArrayOutputStream(); 66 byte[] payload = getTestPayload(); 67 writeShortLE(out, payload.length); 68 out.write(payload); 69 return out.toByteArray(); 70 } catch (Exception e) { 71 return null; 72 } 73 } 74 75 /** 76 * Generate and return the raw data based on pre-defined test data. 77 * 78 * @return byte[] 79 */ getTestDataWithInvalidLength()80 private static byte[] getTestDataWithInvalidLength() { 81 try { 82 ByteArrayOutputStream out = new ByteArrayOutputStream(); 83 byte[] payload = getTestPayload(); 84 // Set length to less than the minimum required. 85 writeShortLE(out, OsuProviderInfo.MINIMUM_LENGTH - 1); 86 out.write(payload); 87 return out.toByteArray(); 88 } catch (Exception e) { 89 return null; 90 } 91 } 92 93 /** 94 * Generate and return the payload containing OSU provider test data, excluding the length 95 * field. 96 * 97 * @return byte[] 98 * @throws IOException 99 */ getTestPayload()100 private static byte[] getTestPayload() throws IOException { 101 ByteArrayOutputStream out = new ByteArrayOutputStream(); 102 103 // Write friendly name list. 104 byte[] friendlyNamesData = getI18NameListData(TEST_FRIENDLY_NAMES); 105 writeShortLE(out, friendlyNamesData.length); 106 out.write(friendlyNamesData); 107 108 // Write server URI. 109 writeByteArrayWithLength(out, TEST_SERVER_URI.getBytes(StandardCharsets.UTF_8)); 110 111 // Write method list. 112 out.write((byte) TEST_METHOD_LIST.size()); 113 for (Integer method : TEST_METHOD_LIST) { 114 out.write((byte) method.intValue()); 115 } 116 117 // Write icon info list. 118 writeShortLE(out, IconInfoTestUtil.TEST_ICON_INFO_RAW_BYTES.length); 119 out.write(IconInfoTestUtil.TEST_ICON_INFO_RAW_BYTES); 120 121 // Write NAI. 122 writeByteArrayWithLength(out, TEST_NAI.getBytes(StandardCharsets.UTF_8)); 123 124 // Write service descriptions. 125 byte[] serviceDescriptionsData = getI18NameListData(TEST_SERVICE_DESCRIPTIONS); 126 writeShortLE(out, serviceDescriptionsData.length); 127 out.write(serviceDescriptionsData); 128 129 return out.toByteArray(); 130 } 131 getI18NameListData(List<I18Name> nameList)132 private static byte[] getI18NameListData(List<I18Name> nameList) throws IOException { 133 ByteArrayOutputStream out = new ByteArrayOutputStream(); 134 for (I18Name name : nameList) { 135 byte[] data = getI18NameData(name); 136 out.write((byte) data.length); 137 out.write(data); 138 } 139 return out.toByteArray(); 140 } 141 142 /** 143 * Format the raw bytes for the given {@link I18Name}. 144 * 145 * @param value The {@link I18Name} to serialize 146 * @return byte[] 147 * @throws IOException 148 */ getI18NameData(I18Name value)149 private static byte[] getI18NameData(I18Name value) throws IOException { 150 ByteArrayOutputStream out = new ByteArrayOutputStream(); 151 out.write(value.getLanguage().getBytes(StandardCharsets.US_ASCII)); 152 out.write((byte) 0); // Padding for language code. 153 out.write(value.getText().getBytes(StandardCharsets.UTF_8)); 154 return out.toByteArray(); 155 } 156 157 /** 158 * Write the lower 2-bytes of an integer to the given output stream in Little-Endian. 159 * 160 * @param out The output stream to write to 161 * @param value The integer value to write 162 */ writeShortLE(ByteArrayOutputStream out, int value)163 private static void writeShortLE(ByteArrayOutputStream out, int value) { 164 out.write(value & 0xFF); 165 out.write((value >> 8) & 0xFF); 166 } 167 168 /** 169 * Write the given byte array to the given output stream, the array data is prefixed with a 170 * byte specifying the length of the byte array. 171 * 172 * @param out The output stream to write to 173 * @param data The byte array to write 174 * @throws IOException 175 */ writeByteArrayWithLength(ByteArrayOutputStream out, byte[] data)176 private static void writeByteArrayWithLength(ByteArrayOutputStream out, byte[] data) 177 throws IOException { 178 out.write((byte) data.length); 179 out.write(data); 180 } 181 } 182