1 /* 2 * Copyright (C) 2010 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 android.mtp; 18 19 import android.annotation.NonNull; 20 import android.os.Build; 21 22 import com.android.internal.util.Preconditions; 23 24 import dalvik.system.VMRuntime; 25 26 /** 27 * This class encapsulates information about an object on an MTP device. 28 * This corresponds to the ObjectInfo Dataset described in 29 * section 5.3.1 of the MTP specification. 30 */ 31 public final class MtpObjectInfo { 32 private int mHandle; 33 private int mStorageId; 34 private int mFormat; 35 private int mProtectionStatus; 36 private int mCompressedSize; 37 private int mThumbFormat; 38 private int mThumbCompressedSize; 39 private int mThumbPixWidth; 40 private int mThumbPixHeight; 41 private int mImagePixWidth; 42 private int mImagePixHeight; 43 private int mImagePixDepth; 44 private int mParent; 45 private int mAssociationType; 46 private int mAssociationDesc; 47 private int mSequenceNumber; 48 private String mName = ""; 49 private long mDateCreated; 50 private long mDateModified; 51 private String mKeywords = ""; 52 53 // only instantiated via JNI or via a builder MtpObjectInfo()54 private MtpObjectInfo() { 55 } 56 57 /** 58 * Returns the object handle for the MTP object 59 * 60 * @return the object handle 61 */ getObjectHandle()62 public final int getObjectHandle() { 63 return mHandle; 64 } 65 66 /** 67 * Returns the storage ID for the MTP object's storage unit 68 * 69 * @return the storage ID 70 */ getStorageId()71 public final int getStorageId() { 72 return mStorageId; 73 } 74 75 /** 76 * Returns the format code for the MTP object 77 * 78 * @return the format code 79 */ getFormat()80 public final int getFormat() { 81 return mFormat; 82 } 83 84 /** 85 * Returns the protection status for the MTP object 86 * Possible values are: 87 * 88 * <ul> 89 * <li> {@link android.mtp.MtpConstants#PROTECTION_STATUS_NONE} 90 * <li> {@link android.mtp.MtpConstants#PROTECTION_STATUS_READ_ONLY} 91 * <li> {@link android.mtp.MtpConstants#PROTECTION_STATUS_NON_TRANSFERABLE_DATA} 92 * </ul> 93 * 94 * @return the protection status 95 */ getProtectionStatus()96 public final int getProtectionStatus() { 97 return mProtectionStatus; 98 } 99 100 /** 101 * Returns the size of the MTP object 102 * 103 * @return the object size 104 */ getCompressedSize()105 public final int getCompressedSize() { 106 Preconditions.checkState(mCompressedSize >= 0); 107 return mCompressedSize; 108 } 109 110 /** 111 * Returns the size of the MTP object 112 * 113 * @return the object size 114 */ getCompressedSizeLong()115 public final long getCompressedSizeLong() { 116 return uint32ToLong(mCompressedSize); 117 } 118 119 /** 120 * Returns the format code for the MTP object's thumbnail 121 * Will be zero for objects with no thumbnail 122 * 123 * @return the thumbnail format code 124 */ getThumbFormat()125 public final int getThumbFormat() { 126 return mThumbFormat; 127 } 128 129 /** 130 * Returns the size of the MTP object's thumbnail 131 * Will be zero for objects with no thumbnail 132 * 133 * @return the thumbnail size 134 */ getThumbCompressedSize()135 public final int getThumbCompressedSize() { 136 Preconditions.checkState(mThumbCompressedSize >= 0); 137 return mThumbCompressedSize; 138 } 139 140 /** 141 * Returns the size of the MTP object's thumbnail 142 * Will be zero for objects with no thumbnail 143 * 144 * @return the thumbnail size 145 */ getThumbCompressedSizeLong()146 public final long getThumbCompressedSizeLong() { 147 return uint32ToLong(mThumbCompressedSize); 148 } 149 150 /** 151 * Returns the width of the MTP object's thumbnail in pixels 152 * Will be zero for objects with no thumbnail 153 * 154 * @return the thumbnail width 155 */ getThumbPixWidth()156 public final int getThumbPixWidth() { 157 Preconditions.checkState(mThumbPixWidth >= 0); 158 return mThumbPixWidth; 159 } 160 161 /** 162 * Returns the width of the MTP object's thumbnail in pixels 163 * Will be zero for objects with no thumbnail 164 * 165 * @return the thumbnail width 166 */ getThumbPixWidthLong()167 public final long getThumbPixWidthLong() { 168 return uint32ToLong(mThumbPixWidth); 169 } 170 171 /** 172 * Returns the height of the MTP object's thumbnail in pixels 173 * Will be zero for objects with no thumbnail 174 * 175 * @return the thumbnail height 176 */ getThumbPixHeight()177 public final int getThumbPixHeight() { 178 Preconditions.checkState(mThumbPixHeight >= 0); 179 return mThumbPixHeight; 180 } 181 182 /** 183 * Returns the height of the MTP object's thumbnail in pixels 184 * Will be zero for objects with no thumbnail 185 * 186 * @return the thumbnail height 187 */ getThumbPixHeightLong()188 public final long getThumbPixHeightLong() { 189 return uint32ToLong(mThumbPixHeight); 190 } 191 192 /** 193 * Returns the width of the MTP object in pixels 194 * Will be zero for non-image objects 195 * 196 * @return the image width 197 */ getImagePixWidth()198 public final int getImagePixWidth() { 199 Preconditions.checkState(mImagePixWidth >= 0); 200 return mImagePixWidth; 201 } 202 203 /** 204 * Returns the width of the MTP object in pixels 205 * Will be zero for non-image objects 206 * 207 * @return the image width 208 */ getImagePixWidthLong()209 public final long getImagePixWidthLong() { 210 return uint32ToLong(mImagePixWidth); 211 } 212 213 /** 214 * Returns the height of the MTP object in pixels 215 * Will be zero for non-image objects 216 * 217 * @return the image height 218 */ getImagePixHeight()219 public final int getImagePixHeight() { 220 Preconditions.checkState(mImagePixHeight >= 0); 221 return mImagePixHeight; 222 } 223 224 /** 225 * Returns the height of the MTP object in pixels 226 * Will be zero for non-image objects 227 * 228 * @return the image height 229 */ getImagePixHeightLong()230 public final long getImagePixHeightLong() { 231 return uint32ToLong(mImagePixHeight); 232 } 233 234 /** 235 * Returns the depth of the MTP object in bits per pixel 236 * Will be zero for non-image objects 237 * 238 * @return the image depth 239 */ getImagePixDepth()240 public final int getImagePixDepth() { 241 Preconditions.checkState(mImagePixDepth >= 0); 242 return mImagePixDepth; 243 } 244 245 /** 246 * Returns the depth of the MTP object in bits per pixel 247 * Will be zero for non-image objects 248 * 249 * @return the image depth 250 */ getImagePixDepthLong()251 public final long getImagePixDepthLong() { 252 return uint32ToLong(mImagePixDepth); 253 } 254 255 /** 256 * Returns the object handle for the object's parent 257 * Will be zero for the root directory of a storage unit 258 * 259 * @return the object's parent 260 */ getParent()261 public final int getParent() { 262 return mParent; 263 } 264 265 /** 266 * Returns the association type for the MTP object 267 * Will be zero objects that are not of format 268 * {@link android.mtp.MtpConstants#FORMAT_ASSOCIATION} 269 * For directories the association type is typically 270 * {@link android.mtp.MtpConstants#ASSOCIATION_TYPE_GENERIC_FOLDER} 271 * 272 * @return the object's association type 273 */ getAssociationType()274 public final int getAssociationType() { 275 return mAssociationType; 276 } 277 278 /** 279 * Returns the association description for the MTP object 280 * Will be zero objects that are not of format 281 * {@link android.mtp.MtpConstants#FORMAT_ASSOCIATION} 282 * 283 * @return the object's association description 284 */ getAssociationDesc()285 public final int getAssociationDesc() { 286 return mAssociationDesc; 287 } 288 289 /** 290 * Returns the sequence number for the MTP object 291 * This field is typically not used for MTP devices, 292 * but is sometimes used to define a sequence of photos 293 * on PTP cameras. 294 * 295 * @return the object's sequence number 296 */ getSequenceNumber()297 public final int getSequenceNumber() { 298 Preconditions.checkState(mSequenceNumber >= 0); 299 return mSequenceNumber; 300 } 301 302 /** 303 * Returns the sequence number for the MTP object 304 * This field is typically not used for MTP devices, 305 * but is sometimes used to define a sequence of photos 306 * on PTP cameras. 307 * 308 * @return the object's sequence number 309 */ getSequenceNumberLong()310 public final long getSequenceNumberLong() { 311 return uint32ToLong(mSequenceNumber); 312 } 313 314 /** 315 * Returns the name of the MTP object 316 * 317 * @return the object's name 318 */ getName()319 public final @NonNull String getName() { 320 return mName; 321 } 322 323 /** 324 * Returns the creation date of the MTP object 325 * The value is represented as milliseconds since January 1, 1970 326 * 327 * @return the object's creation date 328 */ getDateCreated()329 public final long getDateCreated() { 330 return mDateCreated; 331 } 332 333 /** 334 * Returns the modification date of the MTP object 335 * The value is represented as milliseconds since January 1, 1970 336 * 337 * @return the object's modification date 338 */ getDateModified()339 public final long getDateModified() { 340 return mDateModified; 341 } 342 343 /** 344 * Returns a comma separated list of keywords for the MTP object 345 * 346 * @return the object's keyword list 347 */ getKeywords()348 public final @NonNull String getKeywords() { 349 return mKeywords; 350 } 351 352 /** 353 * Builds a new object info instance. 354 */ 355 public static class Builder { 356 private MtpObjectInfo mObjectInfo; 357 Builder()358 public Builder() { 359 mObjectInfo = new MtpObjectInfo(); 360 mObjectInfo.mHandle = -1; 361 } 362 363 /** 364 * Creates a builder on a copy of an existing object info. 365 * All fields, except the object handle will be copied. 366 * 367 * @param objectInfo object info of an existing entry 368 */ Builder(MtpObjectInfo objectInfo)369 public Builder(MtpObjectInfo objectInfo) { 370 mObjectInfo = new MtpObjectInfo(); 371 mObjectInfo.mHandle = -1; 372 mObjectInfo.mAssociationDesc = objectInfo.mAssociationDesc; 373 mObjectInfo.mAssociationType = objectInfo.mAssociationType; 374 mObjectInfo.mCompressedSize = objectInfo.mCompressedSize; 375 mObjectInfo.mDateCreated = objectInfo.mDateCreated; 376 mObjectInfo.mDateModified = objectInfo.mDateModified; 377 mObjectInfo.mFormat = objectInfo.mFormat; 378 mObjectInfo.mImagePixDepth = objectInfo.mImagePixDepth; 379 mObjectInfo.mImagePixHeight = objectInfo.mImagePixHeight; 380 mObjectInfo.mImagePixWidth = objectInfo.mImagePixWidth; 381 mObjectInfo.mKeywords = objectInfo.mKeywords; 382 mObjectInfo.mName = objectInfo.mName; 383 mObjectInfo.mParent = objectInfo.mParent; 384 mObjectInfo.mProtectionStatus = objectInfo.mProtectionStatus; 385 mObjectInfo.mSequenceNumber = objectInfo.mSequenceNumber; 386 mObjectInfo.mStorageId = objectInfo.mStorageId; 387 mObjectInfo.mThumbCompressedSize = objectInfo.mThumbCompressedSize; 388 mObjectInfo.mThumbFormat = objectInfo.mThumbFormat; 389 mObjectInfo.mThumbPixHeight = objectInfo.mThumbPixHeight; 390 mObjectInfo.mThumbPixWidth = objectInfo.mThumbPixWidth; 391 } 392 setObjectHandle(int value)393 public Builder setObjectHandle(int value) { 394 mObjectInfo.mHandle = value; 395 return this; 396 } 397 setAssociationDesc(int value)398 public Builder setAssociationDesc(int value) { 399 mObjectInfo.mAssociationDesc = value; 400 return this; 401 } 402 setAssociationType(int value)403 public Builder setAssociationType(int value) { 404 mObjectInfo.mAssociationType = value; 405 return this; 406 } 407 setCompressedSize(long value)408 public Builder setCompressedSize(long value) { 409 mObjectInfo.mCompressedSize = longToUint32(value, "value"); 410 return this; 411 } 412 setDateCreated(long value)413 public Builder setDateCreated(long value) { 414 mObjectInfo.mDateCreated = value; 415 return this; 416 } 417 setDateModified(long value)418 public Builder setDateModified(long value) { 419 mObjectInfo.mDateModified = value; 420 return this; 421 } 422 setFormat(int value)423 public Builder setFormat(int value) { 424 mObjectInfo.mFormat = value; 425 return this; 426 } 427 setImagePixDepth(long value)428 public Builder setImagePixDepth(long value) { 429 mObjectInfo.mImagePixDepth = longToUint32(value, "value"); 430 return this; 431 } 432 setImagePixHeight(long value)433 public Builder setImagePixHeight(long value) { 434 mObjectInfo.mImagePixHeight = longToUint32(value, "value"); 435 return this; 436 } 437 setImagePixWidth(long value)438 public Builder setImagePixWidth(long value) { 439 mObjectInfo.mImagePixWidth = longToUint32(value, "value"); 440 return this; 441 } 442 setKeywords(@onNull String value)443 public Builder setKeywords(@NonNull String value) { 444 if (VMRuntime.getRuntime().getTargetSdkVersion() > Build.VERSION_CODES.N_MR1) { 445 Preconditions.checkNotNull(value); 446 } else if (value == null) { 447 // Before N_MR1 we accept null value and it was regarded as an empty string in 448 // MtpDevice#sendObjectInfo. 449 value = ""; 450 } 451 mObjectInfo.mKeywords = value; 452 return this; 453 } 454 setName(@onNull String value)455 public Builder setName(@NonNull String value) { 456 Preconditions.checkNotNull(value); 457 mObjectInfo.mName = value; 458 return this; 459 } 460 setParent(int value)461 public Builder setParent(int value) { 462 mObjectInfo.mParent = value; 463 return this; 464 } 465 setProtectionStatus(int value)466 public Builder setProtectionStatus(int value) { 467 mObjectInfo.mProtectionStatus = value; 468 return this; 469 } 470 setSequenceNumber(long value)471 public Builder setSequenceNumber(long value) { 472 mObjectInfo.mSequenceNumber = longToUint32(value, "value"); 473 return this; 474 } 475 setStorageId(int value)476 public Builder setStorageId(int value) { 477 mObjectInfo.mStorageId = value; 478 return this; 479 } 480 setThumbCompressedSize(long value)481 public Builder setThumbCompressedSize(long value) { 482 mObjectInfo.mThumbCompressedSize = longToUint32(value, "value"); 483 return this; 484 } 485 setThumbFormat(int value)486 public Builder setThumbFormat(int value) { 487 mObjectInfo.mThumbFormat = value; 488 return this; 489 } 490 setThumbPixHeight(long value)491 public Builder setThumbPixHeight(long value) { 492 mObjectInfo.mThumbPixHeight = longToUint32(value, "value"); 493 return this; 494 } 495 setThumbPixWidth(long value)496 public Builder setThumbPixWidth(long value) { 497 mObjectInfo.mThumbPixWidth = longToUint32(value, "value"); 498 return this; 499 } 500 501 /** 502 * Builds the object info instance. Once called, methods of the builder 503 * must not be called anymore. 504 * 505 * @return the object info of the newly created file, or NULL in case 506 * of an error. 507 */ build()508 public MtpObjectInfo build() { 509 MtpObjectInfo result = mObjectInfo; 510 mObjectInfo = null; 511 return result; 512 } 513 } 514 uint32ToLong(int value)515 private static long uint32ToLong(int value) { 516 return value < 0 ? 0x100000000L + value : value; 517 } 518 longToUint32(long value, String valueName)519 private static int longToUint32(long value, String valueName) { 520 Preconditions.checkArgumentInRange(value, 0, 0xffffffffL, valueName); 521 return (int) value; 522 } 523 } 524