• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 android.provider.cts.media;
18 
19 import android.content.ContentValues;
20 import android.content.Context;
21 import android.net.Uri;
22 import android.os.Build;
23 import android.os.ParcelFileDescriptor;
24 import android.provider.MediaStore;
25 import android.provider.MediaStore.DownloadColumns;
26 import android.provider.MediaStore.Downloads;
27 import android.provider.MediaStore.MediaColumns;
28 import android.text.format.DateUtils;
29 
30 import androidx.annotation.NonNull;
31 import androidx.annotation.Nullable;
32 import androidx.test.filters.SdkSuppress;
33 
34 import org.junit.Test;
35 
36 import java.io.FileNotFoundException;
37 import java.io.OutputStream;
38 import java.util.Objects;
39 
40 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.R)
41 public class MediaStoreUtils {
42     @Test
testStub()43     public void testStub() {
44     }
45 
46     /**
47      * Create a new pending media item using the given parameters. Pending items
48      * are expected to have a short lifetime, and owners should either
49      * {@link PendingSession#publish()} or {@link PendingSession#abandon()} a
50      * pending item within a few hours after first creating it.
51      *
52      * @return token which can be passed to {@link #openPending(Context, Uri)}
53      *         to work with this pending item.
54      * @see MediaColumns#IS_PENDING
55      * @see MediaStore#setIncludePending(Uri)
56      * @see MediaStore#createPending(Context, PendingParams)
57      * @removed
58      */
59     @Deprecated
createPending(@onNull Context context, @NonNull PendingParams params)60     public static @NonNull Uri createPending(@NonNull Context context,
61             @NonNull PendingParams params) {
62         return context.getContentResolver().insert(params.insertUri, params.insertValues);
63     }
64 
65     /**
66      * Open a pending media item to make progress on it. You can open a pending
67      * item multiple times before finally calling either
68      * {@link PendingSession#publish()} or {@link PendingSession#abandon()}.
69      *
70      * @param uri token which was previously returned from
71      *            {@link #createPending(Context, PendingParams)}.
72      * @removed
73      */
74     @Deprecated
openPending(@onNull Context context, @NonNull Uri uri)75     public static @NonNull PendingSession openPending(@NonNull Context context, @NonNull Uri uri) {
76         return new PendingSession(context, uri);
77     }
78 
79     /**
80      * Parameters that describe a pending media item.
81      *
82      * @removed
83      */
84     @Deprecated
85     public static class PendingParams {
86         /** {@hide} */
87         public final Uri insertUri;
88         /** {@hide} */
89         public final ContentValues insertValues;
90 
91         /**
92          * Create parameters that describe a pending media item.
93          *
94          * @param insertUri the {@code content://} Uri where this pending item
95          *            should be inserted when finally published. For example, to
96          *            publish an image, use
97          *            {@link MediaStore.Images.Media#getContentUri(String)}.
98          */
PendingParams(@onNull Uri insertUri, @NonNull String displayName, @NonNull String mimeType)99         public PendingParams(@NonNull Uri insertUri, @NonNull String displayName,
100                 @NonNull String mimeType) {
101             this.insertUri = Objects.requireNonNull(insertUri);
102             final long now = System.currentTimeMillis() / 1000;
103             this.insertValues = new ContentValues();
104             this.insertValues.put(MediaColumns.DISPLAY_NAME, Objects.requireNonNull(displayName));
105             this.insertValues.put(MediaColumns.MIME_TYPE, Objects.requireNonNull(mimeType));
106             this.insertValues.put(MediaColumns.DATE_ADDED, now);
107             this.insertValues.put(MediaColumns.DATE_MODIFIED, now);
108             this.insertValues.put(MediaColumns.IS_PENDING, 1);
109             this.insertValues.put(MediaColumns.DATE_EXPIRES,
110                     (System.currentTimeMillis() + DateUtils.DAY_IN_MILLIS) / 1000);
111         }
112 
setPath(@ullable String path)113         public void setPath(@Nullable String path) {
114             if (path == null) {
115                 this.insertValues.remove(MediaColumns.RELATIVE_PATH);
116             } else {
117                 this.insertValues.put(MediaColumns.RELATIVE_PATH, path);
118             }
119         }
120 
setIsFavorite(@ullable Boolean isFavorite)121         public void setIsFavorite(@Nullable Boolean isFavorite) {
122             this.insertValues.put(MediaColumns.IS_FAVORITE, isFavorite);
123         }
124 
125         /**
126          * Optionally set the Uri from where the file has been downloaded. This is used
127          * for files being added to {@link Downloads} table.
128          *
129          * @see DownloadColumns#DOWNLOAD_URI
130          */
setDownloadUri(@ullable Uri downloadUri)131         public void setDownloadUri(@Nullable Uri downloadUri) {
132             if (downloadUri == null) {
133                 this.insertValues.remove(DownloadColumns.DOWNLOAD_URI);
134             } else {
135                 this.insertValues.put(DownloadColumns.DOWNLOAD_URI, downloadUri.toString());
136             }
137         }
138 
139         /**
140          * Optionally set the Uri indicating HTTP referer of the file. This is used for
141          * files being added to {@link Downloads} table.
142          *
143          * @see DownloadColumns#REFERER_URI
144          */
setRefererUri(@ullable Uri refererUri)145         public void setRefererUri(@Nullable Uri refererUri) {
146             if (refererUri == null) {
147                 this.insertValues.remove(DownloadColumns.REFERER_URI);
148             } else {
149                 this.insertValues.put(DownloadColumns.REFERER_URI, refererUri.toString());
150             }
151         }
152     }
153 
154     /**
155      * Session actively working on a pending media item. Pending items are
156      * expected to have a short lifetime, and owners should either
157      * {@link PendingSession#publish()} or {@link PendingSession#abandon()} a
158      * pending item within a few hours after first creating it.
159      *
160      * @removed
161      */
162     @Deprecated
163     public static class PendingSession implements AutoCloseable {
164         /** {@hide} */
165         private final Context mContext;
166         /** {@hide} */
167         private final Uri mUri;
168 
169         /** {@hide} */
PendingSession(Context context, Uri uri)170         public PendingSession(Context context, Uri uri) {
171             mContext = Objects.requireNonNull(context);
172             mUri = Objects.requireNonNull(uri);
173         }
174 
175         /**
176          * Open the underlying file representing this media item. When a media
177          * item is successfully completed, you should
178          * {@link ParcelFileDescriptor#close()} and then {@link #publish()} it.
179          *
180          * @see #notifyProgress(int)
181          */
open()182         public @NonNull ParcelFileDescriptor open() throws FileNotFoundException {
183             return mContext.getContentResolver().openFileDescriptor(mUri, "rw");
184         }
185 
186         /**
187          * Open the underlying file representing this media item. When a media
188          * item is successfully completed, you should
189          * {@link OutputStream#close()} and then {@link #publish()} it.
190          *
191          * @see #notifyProgress(int)
192          */
openOutputStream()193         public @NonNull OutputStream openOutputStream() throws FileNotFoundException {
194             return mContext.getContentResolver().openOutputStream(mUri);
195         }
196 
197         /**
198          * When this media item is successfully completed, call this method to
199          * publish and make the final item visible to the user.
200          *
201          * @return the final {@code content://} Uri representing the newly
202          *         published media.
203          */
publish()204         public @NonNull Uri publish() {
205             final ContentValues values = new ContentValues();
206             values.put(MediaColumns.IS_PENDING, 0);
207             values.putNull(MediaColumns.DATE_EXPIRES);
208             mContext.getContentResolver().update(mUri, values, null, null);
209             return mUri;
210         }
211 
212         /**
213          * When this media item has failed to be completed, call this method to
214          * destroy the pending item record and any data related to it.
215          */
abandon()216         public void abandon() {
217             mContext.getContentResolver().delete(mUri, null, null);
218         }
219 
220         @Override
close()221         public void close() {
222             // No resources to close, but at least we can inform people that no
223             // progress is being actively made.
224         }
225     }
226 }
227