1 /* 2 * Copyright (C) 2019 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.bluetooth.avrcpcontroller; 18 19 import android.util.SparseArray; 20 21 import java.util.HashMap; 22 23 /** 24 * Represents an encoding method in which a BIP image is available. 25 * 26 * The encodings supported by this profile include: 27 * - JPEG 28 * - GIF 29 * - WBMP 30 * - PNG 31 * - JPEG2000 32 * - BMP 33 * - USR-xxx 34 * 35 * The tag USR-xxx is used to represent proprietary encodings. The tag shall begin with the string 36 * “USR-” but the implementer assigns the characters of the second half of the string. This tag can 37 * be used by a manufacturer to enable its devices to exchange images under a proprietary encoding. 38 * 39 * Example proprietary encoding: 40 * 41 * - USR-NOKIA-FORMAT1 42 */ 43 public class BipEncoding { 44 public static final int JPEG = 0; 45 public static final int PNG = 1; 46 public static final int BMP = 2; 47 public static final int GIF = 3; 48 public static final int JPEG2000 = 4; 49 public static final int WBMP = 5; 50 public static final int USR_XXX = 6; 51 public static final int UNKNOWN = 7; // i.e 'not assigned' or 'not assigned anything valid' 52 53 private static final HashMap sEncodingNamesToIds = new HashMap<String, Integer>(); 54 static { 55 sEncodingNamesToIds.put("JPEG", JPEG); 56 sEncodingNamesToIds.put("GIF", GIF); 57 sEncodingNamesToIds.put("WBMP", WBMP); 58 sEncodingNamesToIds.put("PNG", PNG); 59 sEncodingNamesToIds.put("JPEG2000", JPEG2000); 60 sEncodingNamesToIds.put("BMP", BMP); 61 } 62 63 private static final SparseArray sIdsToEncodingNames = new SparseArray<String>(); 64 static { sIdsToEncodingNames.put(JPEG, R)65 sIdsToEncodingNames.put(JPEG, "JPEG"); sIdsToEncodingNames.put(GIF, R)66 sIdsToEncodingNames.put(GIF, "GIF"); sIdsToEncodingNames.put(WBMP, R)67 sIdsToEncodingNames.put(WBMP, "WBMP"); sIdsToEncodingNames.put(PNG, R)68 sIdsToEncodingNames.put(PNG, "PNG"); sIdsToEncodingNames.put(JPEG2000, R)69 sIdsToEncodingNames.put(JPEG2000, "JPEG2000"); sIdsToEncodingNames.put(BMP, R)70 sIdsToEncodingNames.put(BMP, "BMP"); sIdsToEncodingNames.put(UNKNOWN, R)71 sIdsToEncodingNames.put(UNKNOWN, "UNKNOWN"); 72 } 73 74 /** 75 * The integer ID of the type that this encoding is 76 */ 77 private final int mType; 78 79 /** 80 * If an encoding is type USR_XXX then it has an extension that defines the encoding 81 */ 82 private final String mProprietaryEncodingId; 83 84 /** 85 * Create an encoding object based on a AVRCP specification defined string of the encoding name 86 * 87 * @param encoding The encoding name 88 */ BipEncoding(String encoding)89 public BipEncoding(String encoding) { 90 if (encoding == null) { 91 throw new ParseException("Encoding input invalid"); 92 } 93 encoding = encoding.trim(); 94 mType = determineEncoding(encoding.toUpperCase()); 95 96 String proprietaryEncodingId = null; 97 if (mType == USR_XXX) { 98 proprietaryEncodingId = encoding.substring(4).toUpperCase(); 99 } 100 mProprietaryEncodingId = proprietaryEncodingId; 101 102 // If we don't have a type by now, we've failed to parse the encoding 103 if (mType == UNKNOWN) { 104 throw new ParseException("Failed to determine type of '" + encoding + "'"); 105 } 106 } 107 108 /** 109 * Create an encoding object based on one of the constants for the available formats 110 * 111 * @param encoding A constant representing an available encoding 112 * @param proprietaryId A string representing the Id of a propreitary encoding. Only used if the 113 * encoding type is BipEncoding.USR_XXX 114 */ BipEncoding(int encoding, String proprietaryId)115 public BipEncoding(int encoding, String proprietaryId) { 116 if (encoding < 0 || encoding > USR_XXX) { 117 throw new IllegalArgumentException("Received invalid encoding type '" + encoding + "'"); 118 } 119 mType = encoding; 120 121 String proprietaryEncodingId = null; 122 if (mType == USR_XXX) { 123 if (proprietaryId == null) { 124 throw new IllegalArgumentException("Received invalid user defined encoding id '" 125 + proprietaryId + "'"); 126 } 127 proprietaryEncodingId = proprietaryId.toUpperCase(); 128 } 129 mProprietaryEncodingId = proprietaryEncodingId; 130 } 131 BipEncoding(int encoding)132 public BipEncoding(int encoding) { 133 this(encoding, null); 134 } 135 136 /** 137 * Returns the encoding type 138 * 139 * @return Integer type ID of the encoding 140 */ getType()141 public int getType() { 142 return mType; 143 } 144 145 /** 146 * Returns the ID portion of an encoding if it's a proprietary encoding 147 * 148 * @return String ID of a proprietary encoding, or null if the encoding is not proprietary 149 */ getProprietaryEncodingId()150 public String getProprietaryEncodingId() { 151 return mProprietaryEncodingId; 152 } 153 154 /** 155 * Determines if an encoding is supported by Android's Graphics Framework 156 * 157 * Android's Bitmap/BitmapFactory can handle BMP, GIF, JPEG, PNG, WebP, and HEIF formats. 158 * 159 * @return True if the encoding is supported, False otherwise. 160 */ isAndroidSupported()161 public boolean isAndroidSupported() { 162 return mType == BipEncoding.JPEG || mType == BipEncoding.PNG || mType == BipEncoding.BMP 163 || mType == BipEncoding.GIF; 164 } 165 166 /** 167 * Determine the encoding type based on an input string 168 */ determineEncoding(String encoding)169 private static int determineEncoding(String encoding) { 170 Integer type = (Integer) sEncodingNamesToIds.get(encoding); 171 if (type != null) return type.intValue(); 172 if (encoding != null && encoding.length() >= 4 && encoding.substring(0, 4).equals("USR-")) { 173 return USR_XXX; 174 } 175 return UNKNOWN; 176 } 177 178 @Override equals(Object o)179 public boolean equals(Object o) { 180 if (o == this) return true; 181 if (!(o instanceof BipEncoding)) return false; 182 183 BipEncoding e = (BipEncoding) o; 184 return e.getType() == getType() 185 && e.getProprietaryEncodingId() == getProprietaryEncodingId(); 186 } 187 188 @Override toString()189 public String toString() { 190 if (mType == USR_XXX) return "USR-" + mProprietaryEncodingId; 191 String encoding = (String) sIdsToEncodingNames.get(mType); 192 return encoding; 193 } 194 } 195