1 /*
2  * Copyright (C) 2008 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.internal.app;
18 
19 import static org.mockito.Mockito.mock;
20 import static org.mockito.Mockito.when;
21 
22 import android.annotation.Nullable;
23 import android.app.usage.UsageStatsManager;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.content.Intent;
27 import android.content.pm.PackageManager;
28 import android.content.pm.ResolveInfo;
29 import android.content.res.Resources;
30 import android.database.Cursor;
31 import android.graphics.Bitmap;
32 import android.net.Uri;
33 import android.os.UserHandle;
34 import android.util.Size;
35 
36 import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
37 import com.android.internal.app.chooser.DisplayResolveInfo;
38 import com.android.internal.app.chooser.TargetInfo;
39 import com.android.internal.logging.MetricsLogger;
40 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
41 
42 import java.util.List;
43 import java.util.function.Function;
44 
45 public class ChooserWrapperActivity extends ChooserActivity {
46     /*
47      * Simple wrapper around chooser activity to be able to initiate it under test
48      */
49     static final OverrideData sOverrides = new OverrideData();
50     private UsageStatsManager mUsm;
51 
52     @Override
createMultiProfilePagerAdapter( Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed)53     protected AbstractMultiProfilePagerAdapter createMultiProfilePagerAdapter(
54             Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed) {
55         AbstractMultiProfilePagerAdapter multiProfilePagerAdapter =
56                 super.createMultiProfilePagerAdapter(initialIntents, rList, filterLastUsed);
57         multiProfilePagerAdapter.setInjector(sOverrides.multiPagerAdapterInjector);
58         return multiProfilePagerAdapter;
59     }
60 
61     @Override
createChooserListAdapter(Context context, List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed, ResolverListController resolverListController)62     public ChooserListAdapter createChooserListAdapter(Context context, List<Intent> payloadIntents,
63             Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed,
64             ResolverListController resolverListController) {
65         PackageManager packageManager =
66                 sOverrides.packageManager == null ? context.getPackageManager()
67                         : sOverrides.packageManager;
68         return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
69                 filterLastUsed, resolverListController,
70                 this, this, packageManager);
71     }
72 
getAdapter()73     ChooserListAdapter getAdapter() {
74         return mChooserMultiProfilePagerAdapter.getActiveListAdapter();
75     }
76 
getPersonalListAdapter()77     ChooserListAdapter getPersonalListAdapter() {
78         return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(0))
79                 .getListAdapter();
80     }
81 
getWorkListAdapter()82     ChooserListAdapter getWorkListAdapter() {
83         if (mMultiProfilePagerAdapter.getInactiveListAdapter() == null) {
84             return null;
85         }
86         return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(1))
87                 .getListAdapter();
88     }
89 
getIsSelected()90     boolean getIsSelected() { return mIsSuccessfullySelected; }
91 
getUsageStatsManager()92     UsageStatsManager getUsageStatsManager() {
93         if (mUsm == null) {
94             mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
95         }
96         return mUsm;
97     }
98 
99     @Override
isVoiceInteraction()100     public boolean isVoiceInteraction() {
101         if (sOverrides.isVoiceInteraction != null) {
102             return sOverrides.isVoiceInteraction;
103         }
104         return super.isVoiceInteraction();
105     }
106 
107     @Override
safelyStartActivity(com.android.internal.app.chooser.TargetInfo cti)108     public void safelyStartActivity(com.android.internal.app.chooser.TargetInfo cti) {
109         if (sOverrides.onSafelyStartCallback != null &&
110                 sOverrides.onSafelyStartCallback.apply(cti)) {
111             return;
112         }
113         super.safelyStartActivity(cti);
114     }
115 
116     @Override
createListController(UserHandle userHandle)117     protected ResolverListController createListController(UserHandle userHandle) {
118         if (userHandle == UserHandle.SYSTEM) {
119             when(sOverrides.resolverListController.getUserHandle()).thenReturn(UserHandle.SYSTEM);
120             return sOverrides.resolverListController;
121         }
122         when(sOverrides.workResolverListController.getUserHandle()).thenReturn(userHandle);
123         return sOverrides.workResolverListController;
124     }
125 
126     @Override
getPackageManager()127     public PackageManager getPackageManager() {
128         if (sOverrides.createPackageManager != null) {
129             return sOverrides.createPackageManager.apply(super.getPackageManager());
130         }
131         return super.getPackageManager();
132     }
133 
134     @Override
getResources()135     public Resources getResources() {
136         if (sOverrides.resources != null) {
137             return sOverrides.resources;
138         }
139         return super.getResources();
140     }
141 
142     @Override
loadThumbnail(Uri uri, Size size)143     protected Bitmap loadThumbnail(Uri uri, Size size) {
144         if (sOverrides.previewThumbnail != null) {
145             return sOverrides.previewThumbnail;
146         }
147         return super.loadThumbnail(uri, size);
148     }
149 
150     @Override
isImageType(String mimeType)151     protected boolean isImageType(String mimeType) {
152         return sOverrides.isImageType;
153     }
154 
155     @Override
getMetricsLogger()156     protected MetricsLogger getMetricsLogger() {
157         return sOverrides.metricsLogger;
158     }
159 
160     @Override
getChooserActivityLogger()161     protected ChooserActivityLogger getChooserActivityLogger() {
162         return sOverrides.chooserActivityLogger;
163     }
164 
165     @Override
queryResolver(ContentResolver resolver, Uri uri)166     public Cursor queryResolver(ContentResolver resolver, Uri uri) {
167         if (sOverrides.resolverCursor != null) {
168             return sOverrides.resolverCursor;
169         }
170 
171         if (sOverrides.resolverForceException) {
172             throw new SecurityException("Test exception handling");
173         }
174 
175         return super.queryResolver(resolver, uri);
176     }
177 
178     @Override
isWorkProfile()179     protected boolean isWorkProfile() {
180         if (sOverrides.alternateProfileSetting != 0) {
181             return sOverrides.alternateProfileSetting == MetricsEvent.MANAGED_PROFILE;
182         }
183         return super.isWorkProfile();
184     }
185 
createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, CharSequence pInfo, Intent replacementIntent, @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter)186     public DisplayResolveInfo createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri,
187             CharSequence pLabel, CharSequence pInfo, Intent replacementIntent,
188             @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter) {
189         return new DisplayResolveInfo(originalIntent, pri, pLabel, pInfo, replacementIntent,
190                 resolveInfoPresentationGetter);
191     }
192 
193     @Override
getWorkProfileUserHandle()194     protected UserHandle getWorkProfileUserHandle() {
195         return sOverrides.workProfileUserHandle;
196     }
197 
getCurrentUserHandle()198     protected UserHandle getCurrentUserHandle() {
199         return mMultiProfilePagerAdapter.getCurrentUserHandle();
200     }
201 
202     @Override
createContextAsUser(UserHandle user, int flags)203     public Context createContextAsUser(UserHandle user, int flags) {
204         // return the current context as a work profile doesn't really exist in these tests
205         return getApplicationContext();
206     }
207 
208     @Override
queryDirectShareTargets(ChooserListAdapter adapter, boolean skipAppPredictionService)209     protected void queryDirectShareTargets(ChooserListAdapter adapter,
210             boolean skipAppPredictionService) {
211         if (sOverrides.onQueryDirectShareTargets != null) {
212             sOverrides.onQueryDirectShareTargets.apply(adapter);
213         }
214         super.queryDirectShareTargets(adapter, skipAppPredictionService);
215     }
216 
217     @Override
queryTargetServices(ChooserListAdapter adapter)218     protected void queryTargetServices(ChooserListAdapter adapter) {
219         if (sOverrides.onQueryTargetServices != null) {
220             sOverrides.onQueryTargetServices.apply(adapter);
221         }
222         super.queryTargetServices(adapter);
223     }
224 
225     @Override
isQuietModeEnabled(UserHandle userHandle)226     protected boolean isQuietModeEnabled(UserHandle userHandle) {
227         return sOverrides.isQuietModeEnabled;
228     }
229 
230     @Override
isUserRunning(UserHandle userHandle)231     protected boolean isUserRunning(UserHandle userHandle) {
232         if (userHandle.equals(UserHandle.SYSTEM)) {
233             return super.isUserRunning(userHandle);
234         }
235         return sOverrides.isWorkProfileUserRunning;
236     }
237 
238     @Override
isUserUnlocked(UserHandle userHandle)239     protected boolean isUserUnlocked(UserHandle userHandle) {
240         if (userHandle.equals(UserHandle.SYSTEM)) {
241             return super.isUserUnlocked(userHandle);
242         }
243         return sOverrides.isWorkProfileUserUnlocked;
244     }
245 
246     /**
247      * We cannot directly mock the activity created since instrumentation creates it.
248      * <p>
249      * Instead, we use static instances of this object to modify behavior.
250      */
251     static class OverrideData {
252         @SuppressWarnings("Since15")
253         public Function<PackageManager, PackageManager> createPackageManager;
254         public Function<TargetInfo, Boolean> onSafelyStartCallback;
255         public Function<ChooserListAdapter, Void> onQueryDirectShareTargets;
256         public Function<ChooserListAdapter, Void> onQueryTargetServices;
257         public ResolverListController resolverListController;
258         public ResolverListController workResolverListController;
259         public Boolean isVoiceInteraction;
260         public boolean isImageType;
261         public Cursor resolverCursor;
262         public boolean resolverForceException;
263         public Bitmap previewThumbnail;
264         public MetricsLogger metricsLogger;
265         public ChooserActivityLogger chooserActivityLogger;
266         public int alternateProfileSetting;
267         public Resources resources;
268         public UserHandle workProfileUserHandle;
269         public boolean hasCrossProfileIntents;
270         public boolean isQuietModeEnabled;
271         public boolean isWorkProfileUserRunning;
272         public boolean isWorkProfileUserUnlocked;
273         public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector;
274         public PackageManager packageManager;
275 
reset()276         public void reset() {
277             onSafelyStartCallback = null;
278             onQueryDirectShareTargets = null;
279             onQueryTargetServices = null;
280             isVoiceInteraction = null;
281             createPackageManager = null;
282             previewThumbnail = null;
283             isImageType = false;
284             resolverCursor = null;
285             resolverForceException = false;
286             resolverListController = mock(ResolverListController.class);
287             workResolverListController = mock(ResolverListController.class);
288             metricsLogger = mock(MetricsLogger.class);
289             chooserActivityLogger = new ChooserActivityLoggerFake();
290             alternateProfileSetting = 0;
291             resources = null;
292             workProfileUserHandle = null;
293             hasCrossProfileIntents = true;
294             isQuietModeEnabled = false;
295             isWorkProfileUserRunning = true;
296             isWorkProfileUserUnlocked = true;
297             packageManager = null;
298             multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() {
299                 @Override
300                 public boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId,
301                         int targetUserId) {
302                     return hasCrossProfileIntents;
303                 }
304 
305                 @Override
306                 public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) {
307                     return isQuietModeEnabled;
308                 }
309 
310                 @Override
311                 public void requestQuietModeEnabled(boolean enabled,
312                         UserHandle workProfileUserHandle) {
313                     isQuietModeEnabled = enabled;
314                 }
315             };
316         }
317     }
318 }
319