• 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.util;
18 
19 import static android.provider.MediaStore.ACTION_PICK_IMAGES;
20 
21 import android.Manifest;
22 import android.app.Instrumentation;
23 import android.content.ComponentName;
24 import android.content.Intent;
25 import android.content.pm.PackageManager;
26 import android.content.pm.ResolveInfo;
27 
28 import androidx.annotation.NonNull;
29 import androidx.test.InstrumentationRegistry;
30 
31 import java.util.concurrent.TimeUnit;
32 import java.util.concurrent.TimeoutException;
33 import java.util.function.Supplier;
34 
35 public class GetContentActivityAliasUtils {
36 
37     private static final long POLLING_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(5);
38     private static final long POLLING_SLEEP_MILLIS = 100;
39 
40     private static ComponentName sComponentName = new ComponentName(
41             getPhotoPickerPackageName(),
42             "com.android.providers.media.photopicker.PhotoPickerGetContentActivity");
43 
enableAndGetOldState()44     public static int enableAndGetOldState() throws Exception {
45         final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
46         final PackageManager packageManager = inst.getContext().getPackageManager();
47         if (isComponentEnabledSetAsExpected(packageManager,
48                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
49             return PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
50         }
51 
52         final int currentState = packageManager.getComponentEnabledSetting(sComponentName);
53 
54         updateComponentEnabledSetting(packageManager,
55                 PackageManager.COMPONENT_ENABLED_STATE_ENABLED);
56 
57         return currentState;
58     }
59 
restoreState(int oldState)60     public static void restoreState(int oldState) throws Exception {
61         final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
62         updateComponentEnabledSetting(inst.getContext().getPackageManager(), oldState);
63     }
64 
65     /**
66      * Clears the package data.
67      */
clearPackageData(String packageName)68     public static void clearPackageData(String packageName) throws Exception {
69         InstrumentationRegistry.getInstrumentation().getUiAutomation()
70                 .executeShellCommand("pm clear " + packageName);
71 
72         // We should ideally be listening to an effective measure to know if package data was
73         // cleared, like listening to a broadcasts or checking a value. But that information is
74         // very package private and not available.
75         Thread.sleep(500);
76     }
77 
getDocumentsUiPackageName()78     public static String getDocumentsUiPackageName() {
79         final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
80         intent.setType("*/*");
81         return getActivityPackageNameFromIntent(intent);
82     }
83 
updateComponentEnabledSetting(PackageManager packageManager, int state)84     private static void updateComponentEnabledSetting(PackageManager packageManager,
85             int state) throws Exception {
86         final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
87         inst.getUiAutomation().adoptShellPermissionIdentity(
88                 Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE);
89         try {
90             packageManager.setComponentEnabledSetting(sComponentName, state,
91                     PackageManager.DONT_KILL_APP);
92         } finally {
93             inst.getUiAutomation().dropShellPermissionIdentity();
94         }
95         waitForComponentToBeInExpectedState(packageManager, state);
96     }
97 
waitForComponentToBeInExpectedState(PackageManager packageManager, int state)98     private static void waitForComponentToBeInExpectedState(PackageManager packageManager,
99             int state) throws Exception {
100         pollForCondition(() -> isComponentEnabledSetAsExpected(packageManager, state),
101                 "Timed out while waiting for component to be enabled");
102     }
103 
pollForCondition(Supplier<Boolean> condition, String errorMessage)104     private static void pollForCondition(Supplier<Boolean> condition, String errorMessage)
105             throws Exception {
106         for (int i = 0; i < POLLING_TIMEOUT_MILLIS / POLLING_SLEEP_MILLIS; i++) {
107             if (condition.get()) {
108                 return;
109             }
110             Thread.sleep(POLLING_SLEEP_MILLIS);
111         }
112         throw new TimeoutException(errorMessage);
113     }
114 
isComponentEnabledSetAsExpected(PackageManager packageManager, int state)115     private static boolean isComponentEnabledSetAsExpected(PackageManager packageManager,
116             int state) {
117         return packageManager.getComponentEnabledSetting(sComponentName) == state;
118     }
119 
120     @NonNull
getPhotoPickerPackageName()121     private static String getPhotoPickerPackageName() {
122         return getActivityPackageNameFromIntent(new Intent(ACTION_PICK_IMAGES));
123     }
124 
125     @NonNull
getActivityPackageNameFromIntent(@onNull Intent intent)126     private static String getActivityPackageNameFromIntent(@NonNull Intent intent) {
127         final Instrumentation inst = InstrumentationRegistry.getInstrumentation();
128         final ResolveInfo ri = inst.getContext().getPackageManager().resolveActivity(intent, 0);
129         return ri.activityInfo.packageName;
130     }
131 }
132