• 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 android.photopicker.cts.util;
18 
19 import android.app.UiAutomation;
20 import android.content.Context;
21 import android.net.Uri;
22 import android.os.Bundle;
23 import android.os.FileUtils;
24 import android.os.UserHandle;
25 import android.photopicker.cts.R;
26 import android.provider.MediaStore;
27 import android.provider.cts.ProviderTestUtils;
28 import android.provider.cts.media.MediaStoreUtils;
29 import android.util.Pair;
30 
31 import androidx.annotation.NonNull;
32 import androidx.test.InstrumentationRegistry;
33 
34 import com.android.compatibility.common.util.ShellUtils;
35 
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.OutputStream;
39 import java.util.ArrayList;
40 import java.util.List;
41 
42 /**
43  * Photo Picker Utility methods for media files creation and deletion.
44  */
45 public class PhotoPickerFilesUtils {
46     public static final String DISPLAY_NAME_PREFIX = "ctsPhotoPicker";
47 
createImagesAndGetUris(int count, int userId)48     public static List<Uri> createImagesAndGetUris(int count, int userId)
49             throws Exception {
50         return createImagesAndGetUris(count, userId, /* isFavorite */ false);
51     }
52 
createImagesAndGetUris(int count, int userId, boolean isFavorite)53     public static List<Uri> createImagesAndGetUris(int count, int userId, boolean isFavorite)
54             throws Exception {
55         List<Pair<Uri, String>> createdImagesData = createImagesAndGetUriAndPath(count, userId,
56                 isFavorite);
57 
58         List<Uri> uriList = new ArrayList<>();
59         for (Pair<Uri, String> createdImageData: createdImagesData) {
60             uriList.add(createdImageData.first);
61         }
62 
63         return uriList;
64     }
65 
66     /**
67      * Create multiple images according to the given parameters and returns the uris and filenames
68      * of the images created.
69      *
70      * @param count number of images to create
71      * @param userId user id to create images in
72      *
73      * @return list of data (uri and filename pair) about the images created
74      */
createImagesAndGetUriAndPath(int count, int userId, boolean isFavorite)75     public static List<Pair<Uri, String>> createImagesAndGetUriAndPath(int count, int userId,
76             boolean isFavorite) throws Exception {
77         List<Pair<Uri, String>> createdImagesData = new ArrayList<>();
78 
79         for (int i = 0; i < count; i++) {
80             Pair<Uri, String> createdImageData = createImage(userId, isFavorite);
81             createdImagesData.add(createdImageData);
82             clearMediaOwner(createdImageData.first, userId);
83         }
84         // Wait for Picker db sync to complete
85         MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
86 
87         return createdImagesData;
88     }
89 
createImage(int userId, boolean isFavorite)90     public static Pair<Uri, String> createImage(int userId, boolean isFavorite) throws Exception {
91         return getPermissionAndStageMedia(R.raw.lg_g4_iso_800_jpg,
92                 MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg", userId, isFavorite);
93     }
94 
createMj2VideosAndGetUris(int count, int userId)95     public static List<Uri> createMj2VideosAndGetUris(int count, int userId) throws Exception {
96         List<Uri> uriList = new ArrayList<>();
97         for (int i = 0; i < count; i++) {
98             final Uri uri = createMj2Video(userId);
99             uriList.add(uri);
100             clearMediaOwner(uri, userId);
101         }
102         // Wait for Picker db sync to complete
103         MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
104 
105         return uriList;
106     }
107 
createVideosAndGetUris(int count, int userId)108     public static List<Uri> createVideosAndGetUris(int count, int userId) throws Exception {
109         List<Uri> uriList = new ArrayList<>();
110         for (int i = 0; i < count; i++) {
111             final Uri uri = createVideo(userId);
112             uriList.add(uri);
113             clearMediaOwner(uri, userId);
114         }
115         // Wait for Picker db sync to complete
116         MediaStore.waitForIdle(InstrumentationRegistry.getContext().getContentResolver());
117 
118         return uriList;
119     }
120 
deleteMedia(Uri uri, Context context)121     public static void deleteMedia(Uri uri, Context context) throws Exception {
122         try {
123             ProviderTestUtils.setOwner(uri, context.getPackageName());
124             context.getContentResolver().delete(uri, Bundle.EMPTY);
125         } catch (Exception ignored) {
126         }
127     }
128 
clearMediaOwner(Uri uri, int userId)129     private static void clearMediaOwner(Uri uri, int userId) throws Exception {
130         final String cmd = String.format(
131                 "content update --uri %s --user %d --bind owner_package_name:n:", uri, userId);
132         ShellUtils.runShellCommand(cmd);
133     }
134 
createMj2Video(int userId)135     private static Uri createMj2Video(int userId) throws Exception {
136         return getPermissionAndStageMedia(R.raw.test_video_mj2,
137                 MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId,
138                 /* isFavorite */ false).first;
139     }
140 
createVideo(int userId)141     private static Uri createVideo(int userId) throws Exception {
142         return getPermissionAndStageMedia(R.raw.test_video,
143                 MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId,
144                 /* isFavorite */ false).first;
145     }
146 
getPermissionAndStageMedia(int resId, Uri collectionUri, String mimeType, int userId, boolean isFavorite)147     private static Pair<Uri, String> getPermissionAndStageMedia(int resId, Uri collectionUri,
148             String mimeType, int userId, boolean isFavorite) throws Exception {
149         UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
150         uiAutomation.adoptShellPermissionIdentity(
151                 android.Manifest.permission.INTERACT_ACROSS_USERS,
152                 android.Manifest.permission.INTERACT_ACROSS_USERS_FULL);
153         try {
154             final Context context = InstrumentationRegistry.getTargetContext();
155             final Context userContext = userId == context.getUserId() ? context :
156                     context.createPackageContextAsUser("android", /* flags= */ 0,
157                             UserHandle.of(userId));
158             return stageMedia(resId, collectionUri, mimeType, userContext, isFavorite);
159         } finally {
160             uiAutomation.dropShellPermissionIdentity();
161         }
162     }
163 
stageMedia(int resId, Uri collectionUri, String mimeType, Context context, boolean isFavorite)164     private static Pair<Uri, String> stageMedia(int resId, Uri collectionUri, String mimeType,
165             Context context, boolean isFavorite) throws IOException {
166         final String displayName = DISPLAY_NAME_PREFIX + System.nanoTime();
167         final MediaStoreUtils.PendingParams params = new MediaStoreUtils.PendingParams(
168                 collectionUri, displayName, mimeType);
169         params.setIsFavorite(isFavorite);
170         final Uri pendingUri = MediaStoreUtils.createPending(context, params);
171         try (MediaStoreUtils.PendingSession session = MediaStoreUtils.openPending(context,
172                 pendingUri)) {
173             try (InputStream source = context.getResources().openRawResource(resId);
174                  OutputStream target = session.openOutputStream()) {
175                 FileUtils.copy(source, target);
176             }
177             return new Pair(session.publish(), displayName);
178         }
179     }
180 
181     @NonNull
createSvgImage(int userId)182     public static Uri createSvgImage(int userId) throws Exception {
183         return getPermissionAndStageMedia(R.raw.lg_g4_iso_800_svg,
184                 MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/svg+xml", userId,
185                 /* isFavorite */ false).first;
186     }
187 
188     @NonNull
createImageWithUnknownMimeType(int userId)189     public static Uri createImageWithUnknownMimeType(int userId) throws Exception {
190         return getPermissionAndStageMedia(R.raw.lg_g4_iso_800_unknown_mime_type,
191                 MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "image/jpeg", userId,
192                 /* isFavorite */ false).first;
193     }
194 
195     @NonNull
createMpegVideo(int userId)196     public static Uri createMpegVideo(int userId) throws Exception {
197         return getPermissionAndStageMedia(R.raw.test_video_mpeg,
198                 MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mpeg", userId,
199                 /* isFavorite */ false).first;
200     }
201 
202     @NonNull
createVideoWithUnknownMimeType(int userId)203     public static Uri createVideoWithUnknownMimeType(int userId) throws Exception {
204         return getPermissionAndStageMedia(R.raw.test_video_unknown_mime_type,
205                 MediaStore.Video.Media.EXTERNAL_CONTENT_URI, "video/mp4", userId,
206                 /* isFavorite */ false).first;
207     }
208 }
209