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.Log; 20 21 import java.util.Objects; 22 23 /** 24 * Describes a single native or variant format available for an image, coming from a 25 * BipImageProperties object. 26 * 27 * This is not an object by specification, per say. It abstracts all the various native and variant 28 * formats available in a given set of image properties. 29 * 30 * This BipImageFormat can be used to choose a specific BipImageDescriptor when downloading an image 31 * 32 * Examples: 33 * <native encoding="JPEG" pixel="1280*1024” size="1048576"/> 34 * <variant encoding="JPEG" pixel="640*480"/> 35 * <variant encoding="JPEG" pixel="160*120"/> 36 * <variant encoding="GIF" pixel="80*60-640*480"/> 37 */ 38 public class BipImageFormat { 39 private static final String TAG = "avrcpcontroller.BipImageFormat"; 40 41 public static final int FORMAT_NATIVE = 0; 42 public static final int FORMAT_VARIANT = 1; 43 44 /** 45 * Create a native BipImageFormat from the given string fields 46 */ parseNative(String encoding, String pixel, String size)47 public static BipImageFormat parseNative(String encoding, String pixel, String size) { 48 return new BipImageFormat(BipImageFormat.FORMAT_NATIVE, encoding, pixel, size, null, null); 49 } 50 51 /** 52 * Create a variant BipImageFormat from the given string fields 53 */ parseVariant(String encoding, String pixel, String maxSize, String transformation)54 public static BipImageFormat parseVariant(String encoding, String pixel, String maxSize, 55 String transformation) { 56 return new BipImageFormat(BipImageFormat.FORMAT_VARIANT, encoding, pixel, null, maxSize, 57 transformation); 58 } 59 60 /** 61 * Create a native BipImageFormat from the given parameters 62 */ createNative(BipEncoding encoding, BipPixel pixel, int size)63 public static BipImageFormat createNative(BipEncoding encoding, BipPixel pixel, int size) { 64 return new BipImageFormat(BipImageFormat.FORMAT_NATIVE, encoding, pixel, size, -1, null); 65 } 66 67 /** 68 * Create a variant BipImageFormat from the given parameters 69 */ createVariant(BipEncoding encoding, BipPixel pixel, int maxSize, BipTransformation transformation)70 public static BipImageFormat createVariant(BipEncoding encoding, BipPixel pixel, int maxSize, 71 BipTransformation transformation) { 72 return new BipImageFormat(BipImageFormat.FORMAT_VARIANT, encoding, pixel, -1, maxSize, 73 transformation); 74 } 75 76 /** 77 * The 'flavor' of this image format, from the format constants above. 78 */ 79 private final int mFormatType; 80 81 /** 82 * The encoding method in which this image is available, required by the specification 83 */ 84 private final BipEncoding mEncoding; 85 86 /** 87 * The pixel size or range of pixel sizes in which the image is available, required by the 88 * specification 89 */ 90 private final BipPixel mPixel; 91 92 /** 93 * The list of supported image transformation methods, any of: 94 * - 'stretch' : Image server is capable of stretching the image to fit a space 95 * - 'fill' : Image server is capable of filling the image padding data to fit a space 96 * - 'crop' : Image server is capable of cropping the image down to fit a space 97 * 98 * Used by the variant type only 99 */ 100 private final BipTransformation mTransformation; 101 102 /** 103 * Size in bytes of the image. 104 * 105 * Used by the native type only 106 */ 107 private final int mSize; 108 109 /** 110 * The estimated maximum size of an image after a transformation is performed. 111 * 112 * Used by the variant type only 113 */ 114 private final int mMaxSize; 115 BipImageFormat(int type, BipEncoding encoding, BipPixel pixel, int size, int maxSize, BipTransformation transformation)116 private BipImageFormat(int type, BipEncoding encoding, BipPixel pixel, int size, int maxSize, 117 BipTransformation transformation) { 118 mFormatType = type; 119 mEncoding = Objects.requireNonNull(encoding, "Encoding cannot be null"); 120 mPixel = Objects.requireNonNull(pixel, "Pixel cannot be null"); 121 mTransformation = transformation; 122 mSize = size; 123 mMaxSize = maxSize; 124 } 125 BipImageFormat(int type, String encoding, String pixel, String size, String maxSize, String transformation)126 private BipImageFormat(int type, String encoding, String pixel, String size, String maxSize, 127 String transformation) { 128 mFormatType = type; 129 mEncoding = new BipEncoding(encoding); 130 mPixel = new BipPixel(pixel); 131 mTransformation = new BipTransformation(transformation); 132 mSize = parseInt(size); 133 mMaxSize = parseInt(maxSize); 134 } 135 parseInt(String s)136 private static int parseInt(String s) { 137 if (s == null) return -1; 138 try { 139 return Integer.parseInt(s); 140 } catch (NumberFormatException e) { 141 error("Failed to parse '" + s + "'"); 142 } 143 return -1; 144 } 145 getType()146 public int getType() { 147 return mFormatType; 148 } 149 getEncoding()150 public BipEncoding getEncoding() { 151 return mEncoding; 152 } 153 getPixel()154 public BipPixel getPixel() { 155 return mPixel; 156 } 157 getTransformation()158 public BipTransformation getTransformation() { 159 return mTransformation; 160 } 161 getSize()162 public int getSize() { 163 return mSize; 164 } 165 getMaxSize()166 public int getMaxSize() { 167 return mMaxSize; 168 } 169 170 @Override equals(Object o)171 public boolean equals(Object o) { 172 if (o == this) return true; 173 if (!(o instanceof BipImageFormat)) return false; 174 175 BipImageFormat f = (BipImageFormat) o; 176 return f.getType() == getType() 177 && f.getEncoding() == getEncoding() 178 && f.getPixel() == getPixel() 179 && f.getTransformation() == getTransformation() 180 && f.getSize() == getSize() 181 && f.getMaxSize() == getMaxSize(); 182 } 183 184 @Override toString()185 public String toString() { 186 if (mEncoding == null || mEncoding.getType() == BipEncoding.UNKNOWN || mPixel == null 187 || mPixel.getType() == BipPixel.TYPE_UNKNOWN) { 188 error("Missing required fields [ " + (mEncoding == null ? "encoding " : "") 189 + (mPixel == null ? "pixel " : "")); 190 return null; 191 } 192 193 StringBuilder sb = new StringBuilder(); 194 switch (mFormatType) { 195 case FORMAT_NATIVE: 196 sb.append("<native"); 197 sb.append(" encoding=\"" + mEncoding.toString() + "\""); 198 sb.append(" pixel=\"" + mPixel.toString() + "\""); 199 if (mSize > -1) { 200 sb.append(" size=\"" + mSize + "\""); 201 } 202 sb.append(" />"); 203 return sb.toString(); 204 case FORMAT_VARIANT: 205 sb.append("<variant"); 206 sb.append(" encoding=\"" + mEncoding.toString() + "\""); 207 sb.append(" pixel=\"" + mPixel.toString() + "\""); 208 if (mTransformation != null && mTransformation.supportsAny()) { 209 sb.append(" transformation=\"" + mTransformation.toString() + "\""); 210 } 211 if (mSize > -1) { 212 sb.append(" size=\"" + mSize + "\""); 213 } 214 if (mMaxSize > -1) { 215 sb.append(" maxsize=\"" + mMaxSize + "\""); 216 } 217 sb.append(" />"); 218 return sb.toString(); 219 default: 220 error("Unsupported format type '" + mFormatType + "'"); 221 } 222 return null; 223 } 224 error(String msg)225 private static void error(String msg) { 226 Log.e(TAG, msg); 227 } 228 } 229