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.text.TextUtils; 20 import android.util.Log; 21 22 import com.android.internal.annotations.VisibleForTesting; 23 import com.android.server.wifi.ByteBufferReader; 24 25 import java.net.ProtocolException; 26 import java.nio.BufferUnderflowException; 27 import java.nio.ByteBuffer; 28 import java.nio.ByteOrder; 29 import java.nio.charset.StandardCharsets; 30 import java.util.Arrays; 31 import java.util.Objects; 32 33 /** 34 * The Icon Binary File vendor specific ANQP Element, 35 * Wi-Fi Alliance Hotspot 2.0 (Release 2) Technical Specification - Version 5.00, 36 * section 4.10. 37 * 38 * Format: 39 * 40 * | Status Code | Type Length | Type | Data Length | Data | 41 * 1 1 variable 2 variable 42 * 43 */ 44 public class HSIconFileElement extends ANQPElement { 45 private static final String TAG = "HSIconFileElement"; 46 47 /** 48 * Icon download status code. 49 */ 50 public static final int STATUS_CODE_SUCCESS = 0; 51 public static final int STATUS_CODE_FILE_NOT_FOUND = 1; 52 public static final int STATUS_CODE_UNSPECIFIED_ERROR = 2; 53 54 private final int mStatusCode; 55 private final String mIconType; 56 private final byte[] mIconData; 57 58 @VisibleForTesting HSIconFileElement(int statusCode, String iconType, byte[] iconData)59 public HSIconFileElement(int statusCode, String iconType, byte[] iconData) { 60 super(Constants.ANQPElementType.HSIconFile); 61 mStatusCode = statusCode; 62 mIconType = iconType; 63 mIconData = iconData; 64 } 65 66 /** 67 * Parse a HSIconFileElement from the given buffer. 68 * 69 * @param payload The buffer to read from 70 * @return {@link HSIconFileElement} 71 * @throws BufferUnderflowException 72 * @throws ProtocolException 73 */ parse(ByteBuffer payload)74 public static HSIconFileElement parse(ByteBuffer payload) 75 throws ProtocolException { 76 // Parse status code. 77 int status = payload.get() & 0xFF; 78 if (status != STATUS_CODE_SUCCESS) { 79 // No more data if status code is not success. 80 Log.e(TAG, "Icon file download failed: " + status); 81 return new HSIconFileElement(status, null, null); 82 } 83 84 // Parse icon type. 85 String iconType = 86 ByteBufferReader.readStringWithByteLength(payload, StandardCharsets.US_ASCII); 87 88 // Parse icon data. 89 int iconDataLength = 90 (int) ByteBufferReader.readInteger(payload, ByteOrder.LITTLE_ENDIAN, 2) & 0xFFFF; 91 byte[] iconData = new byte[iconDataLength]; 92 payload.get(iconData); 93 94 return new HSIconFileElement(status, iconType, iconData); 95 } 96 97 @Override equals(Object thatObject)98 public boolean equals(Object thatObject) { 99 if (this == thatObject) { 100 return true; 101 } 102 if (!(thatObject instanceof HSIconFileElement)) { 103 return false; 104 } 105 HSIconFileElement that = (HSIconFileElement) thatObject; 106 return mStatusCode == that.mStatusCode 107 && TextUtils.equals(mIconType, that.mIconType) 108 && Arrays.equals(mIconData, that.mIconData); 109 } 110 111 @Override hashCode()112 public int hashCode() { 113 return Objects.hash(mStatusCode, mIconType, Arrays.hashCode(mIconData)); 114 } 115 116 @Override toString()117 public String toString() { 118 return "HSIconFileElement{" + "mStatusCode=" + mStatusCode 119 + "mIconType=" + mIconType + "}"; 120 } 121 } 122