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