• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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;
18 
19 import static android.Manifest.permission.READ_DEVICE_CONFIG;
20 import static android.Manifest.permission.WRITE_ALLOWLISTED_DEVICE_CONFIG;
21 import static android.Manifest.permission.WRITE_DEVICE_CONFIG;
22 import static android.photopicker.cts.PickerProviderMediaGenerator.setCloudProvider;
23 import static android.photopicker.cts.PickerProviderMediaGenerator.syncCloudProvider;
24 import static android.photopicker.cts.util.PhotoPickerUiUtils.findAddButton;
25 import static android.photopicker.cts.util.PhotoPickerUiUtils.findItemList;
26 
27 import static com.google.common.truth.Truth.assertThat;
28 import static com.google.common.truth.Truth.assertWithMessage;
29 
30 import android.app.UiAutomation;
31 import android.content.ClipData;
32 import android.content.Context;
33 import android.provider.DeviceConfig;
34 import android.provider.MediaStore;
35 import android.util.Pair;
36 
37 import androidx.annotation.NonNull;
38 import androidx.annotation.Nullable;
39 import androidx.test.InstrumentationRegistry;
40 import androidx.test.uiautomator.UiDevice;
41 import androidx.test.uiautomator.UiObject;
42 
43 import com.android.modules.utils.build.SdkLevel;
44 
45 import java.util.ArrayList;
46 import java.util.Collections;
47 import java.util.List;
48 
49 public class PhotoPickerCloudUtils {
50     private static final String NAMESPACE_STORAGE_NATIVE_BOOT = "storage_native_boot";
51     private static final String KEY_ALLOWED_CLOUD_PROVIDERS = "allowed_cloud_providers";
52     private static final String KEY_CLOUD_MEDIA_FEATURE_ENABLED = "cloud_media_feature_enabled";
53 
extractMediaIds(ClipData clipData, int minCount)54     public static List<String> extractMediaIds(ClipData clipData, int minCount) {
55         final int count = clipData.getItemCount();
56         assertThat(count).isAtLeast(minCount);
57 
58         final List<String> mediaIds = new ArrayList<>();
59         for (int i = 0; i < count; i++) {
60             mediaIds.add(clipData.getItemAt(i).getUri().getLastPathSegment());
61         }
62 
63         return mediaIds;
64     }
65 
selectAndAddPickerMedia(UiDevice uiDevice, int maxCount)66     public static void selectAndAddPickerMedia(UiDevice uiDevice, int maxCount)
67             throws Exception {
68         final List<UiObject> itemList = findItemList(maxCount);
69         for (int i = 0; i < itemList.size(); i++) {
70             final UiObject item = itemList.get(i);
71             item.click();
72             uiDevice.waitForIdle();
73         }
74 
75         final UiObject addButton = findAddButton();
76         addButton.click();
77         uiDevice.waitForIdle();
78     }
79 
fetchPickerMedia(GetResultActivity activity, UiDevice uiDevice, int maxCount)80     public static ClipData fetchPickerMedia(GetResultActivity activity, UiDevice uiDevice,
81             int maxCount) throws Exception {
82         selectAndAddPickerMedia(uiDevice, maxCount);
83 
84         return activity.getResult().data.getClipData();
85     }
86 
initCloudProviderWithImage( Context context, PickerProviderMediaGenerator.MediaGenerator mediaGenerator, String authority, Pair<String, String>... mediaPairs)87     public static void initCloudProviderWithImage(
88             Context context, PickerProviderMediaGenerator.MediaGenerator mediaGenerator,
89             String authority, Pair<String, String>... mediaPairs) throws Exception {
90         setCloudProvider(context, authority);
91         assertThat(MediaStore.isCurrentCloudMediaProviderAuthority(context.getContentResolver(),
92                 authority)).isTrue();
93 
94         for (Pair<String, String> pair : mediaPairs) {
95             addImage(mediaGenerator, pair.first, pair.second);
96         }
97 
98         syncCloudProvider(context);
99     }
100 
addImage(PickerProviderMediaGenerator.MediaGenerator generator, String localId, String cloudId)101     public static void addImage(PickerProviderMediaGenerator.MediaGenerator generator,
102             String localId, String cloudId)
103             throws Exception {
104         final long imageSizeBytes = 107684;
105         generator.addMedia(localId, cloudId, /* albumId */ null, "image/jpeg",
106                 /* mimeTypeExtension */ 0, imageSizeBytes, /* isFavorite */ false,
107                 R.raw.lg_g4_iso_800_jpg);
108     }
109 
containsExcept(List<String> mediaIds, String contained, String notContained)110     public static void containsExcept(List<String> mediaIds, String contained,
111             String notContained) {
112         assertThat(mediaIds).contains(contained);
113         assertThat(mediaIds).containsNoneIn(Collections.singletonList(notContained));
114     }
115 
isCloudMediaEnabled()116     public static boolean isCloudMediaEnabled() {
117         return Boolean.parseBoolean(readDeviceConfigProp(KEY_CLOUD_MEDIA_FEATURE_ENABLED));
118     }
119 
120     @Nullable
getAllowedProvidersDeviceConfig()121     static String getAllowedProvidersDeviceConfig() {
122         return readDeviceConfigProp(KEY_ALLOWED_CLOUD_PROVIDERS);
123     }
124 
enableCloudMediaAndSetAllowedCloudProviders(@onNull String allowedPackagesJoined)125     static void enableCloudMediaAndSetAllowedCloudProviders(@NonNull String allowedPackagesJoined) {
126         writeDeviceConfigProp(KEY_ALLOWED_CLOUD_PROVIDERS, allowedPackagesJoined);
127         assertWithMessage("Failed to update the allowed cloud providers device config")
128                 .that(getAllowedProvidersDeviceConfig())
129                 .isEqualTo(allowedPackagesJoined);
130 
131         writeDeviceConfigProp(KEY_CLOUD_MEDIA_FEATURE_ENABLED, true);
132     }
133 
134 
disableCloudMediaAndClearAllowedCloudProviders()135     static void disableCloudMediaAndClearAllowedCloudProviders() {
136         writeDeviceConfigProp(KEY_CLOUD_MEDIA_FEATURE_ENABLED, false);
137 
138         deleteDeviceConfigProp(KEY_ALLOWED_CLOUD_PROVIDERS);
139         assertWithMessage("Failed to delete the allowed cloud providers device config")
140                 .that(getAllowedProvidersDeviceConfig())
141                 .isNull();
142     }
143 
144     @NonNull
getUiAutomation()145     private static UiAutomation getUiAutomation() {
146         return InstrumentationRegistry.getInstrumentation().getUiAutomation();
147     }
148 
149     @Nullable
readDeviceConfigProp(@onNull String name)150     private static String readDeviceConfigProp(@NonNull String name) {
151         getUiAutomation().adoptShellPermissionIdentity(READ_DEVICE_CONFIG);
152         try {
153             return DeviceConfig.getProperty(NAMESPACE_STORAGE_NATIVE_BOOT, name);
154         } finally {
155             getUiAutomation().dropShellPermissionIdentity();
156         }
157     }
158 
writeDeviceConfigProp(@onNull String name, boolean value)159     private static void writeDeviceConfigProp(@NonNull String name, boolean value) {
160         writeDeviceConfigProp(name, Boolean.toString(value));
161     }
162 
writeDeviceConfigProp(@onNull String name, @NonNull String value)163     private static void writeDeviceConfigProp(@NonNull String name, @NonNull String value) {
164         if (SdkLevel.isAtLeastU()) {
165             getUiAutomation().adoptShellPermissionIdentity(WRITE_ALLOWLISTED_DEVICE_CONFIG);
166         } else {
167             getUiAutomation().adoptShellPermissionIdentity(WRITE_DEVICE_CONFIG);
168         }
169         try {
170             DeviceConfig.setProperty(NAMESPACE_STORAGE_NATIVE_BOOT, name, value,
171                     /* makeDefault*/ false);
172         } finally {
173             getUiAutomation().dropShellPermissionIdentity();
174         }
175     }
176 
deleteDeviceConfigProp(@onNull String name)177     private static void deleteDeviceConfigProp(@NonNull String name) {
178         DeviceConfig.deleteProperty(NAMESPACE_STORAGE_NATIVE_BOOT, name);
179     }
180 }
181