• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.providers.media.photopicker.data.model;
18 
19 import static android.provider.CloudMediaProviderContract.MediaColumns;
20 import static android.provider.MediaStore.Files.FileColumns._SPECIAL_FORMAT_ANIMATED_WEBP;
21 import static android.provider.MediaStore.Files.FileColumns._SPECIAL_FORMAT_GIF;
22 import static android.provider.MediaStore.Files.FileColumns._SPECIAL_FORMAT_MOTION_PHOTO;
23 
24 import static com.android.providers.media.photopicker.util.CursorUtils.getCursorInt;
25 import static com.android.providers.media.photopicker.util.CursorUtils.getCursorLong;
26 import static com.android.providers.media.photopicker.util.CursorUtils.getCursorString;
27 
28 import android.content.Context;
29 import android.database.Cursor;
30 import android.net.Uri;
31 import android.os.Bundle;
32 import android.provider.CloudMediaProviderContract;
33 import android.provider.MediaStore;
34 import android.text.format.DateUtils;
35 
36 import androidx.annotation.NonNull;
37 import androidx.annotation.VisibleForTesting;
38 
39 import com.android.providers.media.R;
40 import com.android.providers.media.photopicker.data.ItemsProvider;
41 import com.android.providers.media.photopicker.util.DateTimeUtils;
42 import com.android.providers.media.util.MimeUtils;
43 
44 /**
45  * Base class representing one single entity/item in the PhotoPicker.
46  */
47 public class Item {
48     private String mId;
49     private long mDateTaken;
50     private long mGenerationModified;
51     private long mDuration;
52     private String mMimeType;
53     private Uri mUri;
54     private boolean mIsImage;
55     private boolean mIsVideo;
56     private int mSpecialFormat;
57     private boolean mIsDate;
58 
Item()59     private Item() {}
60 
Item(@onNull Cursor cursor, @NonNull UserId userId)61     public Item(@NonNull Cursor cursor, @NonNull UserId userId) {
62         updateFromCursor(cursor, userId);
63     }
64 
65     @VisibleForTesting
Item(String id, String mimeType, long dateTaken, long generationModified, long duration, Uri uri, int specialFormat)66     public Item(String id, String mimeType, long dateTaken, long generationModified, long duration,
67             Uri uri, int specialFormat) {
68         mId = id;
69         mMimeType = mimeType;
70         mDateTaken = dateTaken;
71         mGenerationModified = generationModified;
72         mDuration = duration;
73         mUri = uri;
74         mSpecialFormat = specialFormat;
75         parseMimeType();
76     }
77 
getId()78     public String getId() {
79         return mId;
80     }
81 
isImage()82     public boolean isImage() {
83         return mIsImage;
84     }
85 
isVideo()86     public boolean isVideo() {
87         return mIsVideo;
88     }
89 
isGifOrAnimatedWebp()90     public boolean isGifOrAnimatedWebp() {
91         return isGif() || isAnimatedWebp();
92     }
93 
isGif()94     public boolean isGif() {
95         return mSpecialFormat == _SPECIAL_FORMAT_GIF;
96     }
97 
isAnimatedWebp()98     public boolean isAnimatedWebp() {
99         return mSpecialFormat == _SPECIAL_FORMAT_ANIMATED_WEBP;
100     }
101 
isMotionPhoto()102     public boolean isMotionPhoto() {
103         return mSpecialFormat == _SPECIAL_FORMAT_MOTION_PHOTO;
104     }
105 
isDate()106     public boolean isDate() {
107         return mIsDate;
108     }
109 
getContentUri()110     public Uri getContentUri() {
111         return mUri;
112     }
113 
getDuration()114     public long getDuration() {
115         return mDuration;
116     }
117 
getMimeType()118     public String getMimeType() {
119         return mMimeType;
120     }
121 
getDateTaken()122     public long getDateTaken() {
123         return mDateTaken;
124     }
125 
getGenerationModified()126     public long getGenerationModified() {
127         return mGenerationModified;
128     }
129 
130     @VisibleForTesting
getSpecialFormat()131     public int getSpecialFormat() {
132         return mSpecialFormat;
133     }
134 
fromCursor(Cursor cursor, UserId userId)135     public static Item fromCursor(Cursor cursor, UserId userId) {
136         assert(cursor != null);
137         final Item item = new Item(cursor, userId);
138         return item;
139     }
140 
141     /**
142      * Return the date item. If dateTaken is 0, it is a recent item.
143      * @param dateTaken the time of date taken. The unit is in milliseconds
144      *                  since January 1, 1970 00:00:00.0 UTC.
145      * @return the item with date type
146      */
createDateItem(long dateTaken)147     public static Item createDateItem(long dateTaken) {
148         final Item item = new Item();
149         item.mIsDate = true;
150         item.mDateTaken = dateTaken;
151         return item;
152     }
153 
154     /**
155      * Update the item based on the cursor
156      *
157      * @param cursor the cursor to update the data
158      * @param userId the user id to create an {@link Item} for
159      */
updateFromCursor(@onNull Cursor cursor, @NonNull UserId userId)160     public void updateFromCursor(@NonNull Cursor cursor, @NonNull UserId userId) {
161         final String authority = getCursorString(cursor, MediaColumns.AUTHORITY);
162         mId = getCursorString(cursor, MediaColumns.ID);
163         mMimeType = getCursorString(cursor, MediaColumns.MIME_TYPE);
164         mDateTaken = getCursorLong(cursor, MediaColumns.DATE_TAKEN_MILLIS);
165         mGenerationModified = getCursorLong(cursor, MediaColumns.SYNC_GENERATION);
166         mDuration = getCursorLong(cursor, MediaColumns.DURATION_MILLIS);
167         mSpecialFormat = getCursorInt(cursor, MediaColumns.STANDARD_MIME_TYPE_EXTENSION);
168         mUri = ItemsProvider.getItemsUri(mId, authority, userId);
169 
170         parseMimeType();
171     }
172 
getContentDescription(@onNull Context context)173     public String getContentDescription(@NonNull Context context) {
174         if (isVideo()) {
175             return context.getString(R.string.picker_video_item_content_desc,
176                     DateTimeUtils.getDateTimeStringForContentDesc(getDateTaken()),
177                     getDurationText());
178         }
179 
180         final String itemType;
181         if (isGif() || isAnimatedWebp()) {
182             itemType = context.getString(R.string.picker_gif);
183         } else if (isMotionPhoto()) {
184             itemType = context.getString(R.string.picker_motion_photo);
185         } else {
186             itemType = context.getString(R.string.picker_photo);
187         }
188 
189         return context.getString(R.string.picker_item_content_desc, itemType,
190                 DateTimeUtils.getDateTimeStringForContentDesc(getDateTaken()));
191     }
192 
getDurationText()193     public String getDurationText() {
194         if (mDuration == -1) {
195             return "";
196         }
197         return DateUtils.formatElapsedTime(mDuration / 1000);
198     }
199 
parseMimeType()200     private void parseMimeType() {
201         if (MimeUtils.isImageMimeType(mMimeType)) {
202             mIsImage = true;
203         } else if (MimeUtils.isVideoMimeType(mMimeType)) {
204             mIsVideo = true;
205         }
206     }
207 
208     /**
209      * Compares this item with given {@code anotherItem} by comparing
210      * {@link Item#getDateTaken()} value. When {@link Item#getDateTaken()} is
211      * same, Items are compared based on {@link Item#getId}.
212      */
compareTo(Item anotherItem)213     public int compareTo(Item anotherItem) {
214         if (mDateTaken > anotherItem.getDateTaken()) {
215             return 1;
216         } else if (mDateTaken < anotherItem.getDateTaken()) {
217             return -1;
218         } else {
219             return mId.compareTo(anotherItem.getId());
220         }
221     }
222 }
223