1 /* 2 * Copyright (C) 2006 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.internal.util; 18 19 import android.annotation.Nullable; 20 import android.compat.annotation.UnsupportedAppUsage; 21 22 // Exported to Mainline modules; cannot use annotations 23 // @android.ravenwood.annotation.RavenwoodKeepWholeClass 24 public class HexDump 25 { 26 private final static char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; 27 private final static char[] HEX_LOWER_CASE_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; 28 dumpHexString(@ullable byte[] array)29 public static String dumpHexString(@Nullable byte[] array) { 30 if (array == null) return "(null)"; 31 return dumpHexString(array, 0, array.length); 32 } 33 dumpHexString(@ullable byte[] array, int offset, int length)34 public static String dumpHexString(@Nullable byte[] array, int offset, int length) 35 { 36 if (array == null) return "(null)"; 37 StringBuilder result = new StringBuilder(); 38 39 byte[] line = new byte[16]; 40 int lineIndex = 0; 41 42 result.append("\n0x"); 43 result.append(toHexString(offset)); 44 45 for (int i = offset ; i < offset + length ; i++) 46 { 47 if (lineIndex == 16) 48 { 49 result.append(" "); 50 51 for (int j = 0 ; j < 16 ; j++) 52 { 53 if (line[j] > ' ' && line[j] < '~') 54 { 55 result.append(new String(line, j, 1)); 56 } 57 else 58 { 59 result.append("."); 60 } 61 } 62 63 result.append("\n0x"); 64 result.append(toHexString(i)); 65 lineIndex = 0; 66 } 67 68 byte b = array[i]; 69 result.append(" "); 70 result.append(HEX_DIGITS[(b >>> 4) & 0x0F]); 71 result.append(HEX_DIGITS[b & 0x0F]); 72 73 line[lineIndex++] = b; 74 } 75 76 if (lineIndex != 16) 77 { 78 int count = (16 - lineIndex) * 3; 79 count++; 80 for (int i = 0 ; i < count ; i++) 81 { 82 result.append(" "); 83 } 84 85 for (int i = 0 ; i < lineIndex ; i++) 86 { 87 if (line[i] > ' ' && line[i] < '~') 88 { 89 result.append(new String(line, i, 1)); 90 } 91 else 92 { 93 result.append("."); 94 } 95 } 96 } 97 98 return result.toString(); 99 } 100 toHexString(byte b)101 public static String toHexString(byte b) 102 { 103 return toHexString(toByteArray(b)); 104 } 105 106 @UnsupportedAppUsage toHexString(byte[] array)107 public static String toHexString(byte[] array) 108 { 109 return toHexString(array, 0, array.length, true); 110 } 111 112 @UnsupportedAppUsage(maxTargetSdk = 30, trackingBug = 170729553) toHexString(byte[] array, boolean upperCase)113 public static String toHexString(byte[] array, boolean upperCase) 114 { 115 return toHexString(array, 0, array.length, upperCase); 116 } 117 118 @UnsupportedAppUsage toHexString(byte[] array, int offset, int length)119 public static String toHexString(byte[] array, int offset, int length) 120 { 121 return toHexString(array, offset, length, true); 122 } 123 toHexString(byte[] array, int offset, int length, boolean upperCase)124 public static String toHexString(byte[] array, int offset, int length, boolean upperCase) 125 { 126 char[] digits = upperCase ? HEX_DIGITS : HEX_LOWER_CASE_DIGITS; 127 char[] buf = new char[length * 2]; 128 129 int bufIndex = 0; 130 for (int i = offset ; i < offset + length; i++) 131 { 132 byte b = array[i]; 133 buf[bufIndex++] = digits[(b >>> 4) & 0x0F]; 134 buf[bufIndex++] = digits[b & 0x0F]; 135 } 136 137 return new String(buf); 138 } 139 140 @UnsupportedAppUsage toHexString(int i)141 public static String toHexString(int i) 142 { 143 return toHexString(toByteArray(i)); 144 } 145 toByteArray(byte b)146 public static byte[] toByteArray(byte b) 147 { 148 byte[] array = new byte[1]; 149 array[0] = b; 150 return array; 151 } 152 toByteArray(int i)153 public static byte[] toByteArray(int i) 154 { 155 byte[] array = new byte[4]; 156 157 array[3] = (byte)(i & 0xFF); 158 array[2] = (byte)((i >> 8) & 0xFF); 159 array[1] = (byte)((i >> 16) & 0xFF); 160 array[0] = (byte)((i >> 24) & 0xFF); 161 162 return array; 163 } 164 toByte(char c)165 private static int toByte(char c) 166 { 167 if (c >= '0' && c <= '9') return (c - '0'); 168 if (c >= 'A' && c <= 'F') return (c - 'A' + 10); 169 if (c >= 'a' && c <= 'f') return (c - 'a' + 10); 170 171 throw new RuntimeException ("Invalid hex char '" + c + "'"); 172 } 173 174 @UnsupportedAppUsage hexStringToByteArray(String hexString)175 public static byte[] hexStringToByteArray(String hexString) 176 { 177 int length = hexString.length(); 178 byte[] buffer = new byte[length / 2]; 179 180 for (int i = 0 ; i < length ; i += 2) 181 { 182 buffer[i / 2] = (byte)((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i+1))); 183 } 184 185 return buffer; 186 } 187 appendByteAsHex(StringBuilder sb, byte b, boolean upperCase)188 public static StringBuilder appendByteAsHex(StringBuilder sb, byte b, boolean upperCase) { 189 char[] digits = upperCase ? HEX_DIGITS : HEX_LOWER_CASE_DIGITS; 190 sb.append(digits[(b >> 4) & 0xf]); 191 sb.append(digits[b & 0xf]); 192 return sb; 193 } 194 195 } 196