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.when;
20 
21 import android.annotation.Nullable;
22 import android.app.usage.UsageStatsManager;
23 import android.content.ComponentName;
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.Bundle;
34 import android.os.UserHandle;
35 import android.util.Pair;
36 import android.util.Size;
37 
38 import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
39 import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
40 import com.android.internal.app.chooser.DisplayResolveInfo;
41 import com.android.internal.app.chooser.TargetInfo;
42 import com.android.internal.logging.MetricsLogger;
43 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
44 
45 import java.util.List;
46 
47 /**
48  * Simple wrapper around chooser activity to be able to initiate it under test with overrides
49  * specified in the {@code ChooserActivityOverrideData} singleton. This should be copy-and-pasted
50  * verbatim to test other {@code ChooserActivity} subclasses (updating only the `extends` to match
51  * the concrete activity under test).
52  */
53 public class ChooserWrapperActivity extends ChooserActivity implements IChooserWrapper {
54     static final ChooserActivityOverrideData sOverrides = ChooserActivityOverrideData.getInstance();
55     private UsageStatsManager mUsm;
56 
57     // ResolverActivity (the base class of ChooserActivity) inspects the launched-from UID at
58     // onCreate and needs to see some non-negative value in the test.
59     @Override
getLaunchedFromUid()60     public int getLaunchedFromUid() {
61         return 1234;
62     }
63 
64     @Override
createChooserListAdapter(Context context, List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed, UserHandle userHandle)65     public ChooserListAdapter createChooserListAdapter(Context context, List<Intent> payloadIntents,
66             Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed,
67             UserHandle userHandle) {
68         PackageManager packageManager =
69                 sOverrides.packageManager == null ? context.getPackageManager()
70                         : sOverrides.packageManager;
71         return new ChooserListAdapter(context, payloadIntents, initialIntents, rList,
72                 filterLastUsed, createListController(userHandle),
73                 this, this, packageManager,
74                 getChooserActivityLogger(), userHandle);
75     }
76 
77     @Override
getAdapter()78     public ChooserListAdapter getAdapter() {
79         return mChooserMultiProfilePagerAdapter.getActiveListAdapter();
80     }
81 
82     @Override
getPersonalListAdapter()83     public ChooserListAdapter getPersonalListAdapter() {
84         return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(0))
85                 .getListAdapter();
86     }
87 
88     @Override
getWorkListAdapter()89     public ChooserListAdapter getWorkListAdapter() {
90         if (mMultiProfilePagerAdapter.getInactiveListAdapter() == null) {
91             return null;
92         }
93         return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(1))
94                 .getListAdapter();
95     }
96 
97     @Override
getIsSelected()98     public boolean getIsSelected() {
99         return mIsSuccessfullySelected;
100     }
101 
102     @Override
getNearbySharingComponent()103     protected ComponentName getNearbySharingComponent() {
104         // an arbitrary pre-installed activity that handles this type of intent
105         return ComponentName.unflattenFromString("com.google.android.apps.messaging/"
106                 + "com.google.android.apps.messaging.ui.conversationlist.ShareIntentActivity");
107     }
108 
109     @Override
getNearbySharingTarget(Intent originalIntent)110     protected TargetInfo getNearbySharingTarget(Intent originalIntent) {
111         return new ChooserWrapperActivity.EmptyTargetInfo();
112     }
113 
114     @Override
getUsageStatsManager()115     public UsageStatsManager getUsageStatsManager() {
116         if (mUsm == null) {
117             mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE);
118         }
119         return mUsm;
120     }
121 
122     @Override
isVoiceInteraction()123     public boolean isVoiceInteraction() {
124         if (sOverrides.isVoiceInteraction != null) {
125             return sOverrides.isVoiceInteraction;
126         }
127         return super.isVoiceInteraction();
128     }
129 
130     @Override
createCrossProfileIntentsChecker()131     protected CrossProfileIntentsChecker createCrossProfileIntentsChecker() {
132         if (sOverrides.mCrossProfileIntentsChecker != null) {
133             return sOverrides.mCrossProfileIntentsChecker;
134         }
135         return super.createCrossProfileIntentsChecker();
136     }
137 
138     @Override
createQuietModeManager()139     protected AbstractMultiProfilePagerAdapter.QuietModeManager createQuietModeManager() {
140         if (sOverrides.mQuietModeManager != null) {
141             return sOverrides.mQuietModeManager;
142         }
143         return super.createQuietModeManager();
144     }
145 
146     @Override
safelyStartActivityInternal(TargetInfo cti, UserHandle user, @Nullable Bundle options)147     public void safelyStartActivityInternal(TargetInfo cti, UserHandle user,
148             @Nullable Bundle options) {
149         if (sOverrides.onSafelyStartInternalCallback != null
150                 && sOverrides.onSafelyStartInternalCallback.apply(cti)) {
151             return;
152         }
153         super.safelyStartActivityInternal(cti, user, options);
154     }
155 
156     @Override
createListController(UserHandle userHandle)157     protected ResolverListController createListController(UserHandle userHandle) {
158         if (userHandle == UserHandle.SYSTEM) {
159             when(sOverrides.resolverListController.getUserHandle()).thenReturn(UserHandle.SYSTEM);
160             return sOverrides.resolverListController;
161         }
162         when(sOverrides.workResolverListController.getUserHandle()).thenReturn(userHandle);
163         return sOverrides.workResolverListController;
164     }
165 
166     @Override
getPackageManager()167     public PackageManager getPackageManager() {
168         if (sOverrides.createPackageManager != null) {
169             return sOverrides.createPackageManager.apply(super.getPackageManager());
170         }
171         return super.getPackageManager();
172     }
173 
174     @Override
getResources()175     public Resources getResources() {
176         if (sOverrides.resources != null) {
177             return sOverrides.resources;
178         }
179         return super.getResources();
180     }
181 
182     @Override
loadThumbnail(Uri uri, Size size)183     protected Bitmap loadThumbnail(Uri uri, Size size) {
184         if (sOverrides.previewThumbnail != null) {
185             return sOverrides.previewThumbnail;
186         }
187         return super.loadThumbnail(uri, size);
188     }
189 
190     @Override
isImageType(String mimeType)191     protected boolean isImageType(String mimeType) {
192         return sOverrides.isImageType;
193     }
194 
195     @Override
getMetricsLogger()196     protected MetricsLogger getMetricsLogger() {
197         return sOverrides.metricsLogger;
198     }
199 
200     @Override
getChooserActivityLogger()201     public ChooserActivityLogger getChooserActivityLogger() {
202         return sOverrides.chooserActivityLogger;
203     }
204 
205     @Override
queryResolver(ContentResolver resolver, Uri uri)206     public Cursor queryResolver(ContentResolver resolver, Uri uri) {
207         if (sOverrides.resolverCursor != null) {
208             return sOverrides.resolverCursor;
209         }
210 
211         if (sOverrides.resolverForceException) {
212             throw new SecurityException("Test exception handling");
213         }
214 
215         return super.queryResolver(resolver, uri);
216     }
217 
218     @Override
isWorkProfile()219     protected boolean isWorkProfile() {
220         if (sOverrides.alternateProfileSetting != 0) {
221             return sOverrides.alternateProfileSetting == MetricsEvent.MANAGED_PROFILE;
222         }
223         return super.isWorkProfile();
224     }
225 
226     @Override
createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, CharSequence pInfo, Intent replacementIntent, @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter)227     public DisplayResolveInfo createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri,
228             CharSequence pLabel, CharSequence pInfo, Intent replacementIntent,
229             @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter) {
230         return new DisplayResolveInfo(originalIntent, pri, pLabel, pInfo, replacementIntent,
231                 resolveInfoPresentationGetter);
232     }
233 
234     @Override
getWorkProfileUserHandle()235     protected UserHandle getWorkProfileUserHandle() {
236         return sOverrides.workProfileUserHandle;
237     }
238 
239     @Override
getCurrentUserHandle()240     public UserHandle getCurrentUserHandle() {
241         return mMultiProfilePagerAdapter.getCurrentUserHandle();
242     }
243 
244     @Override
getTabOwnerUserHandleForLaunch()245     protected UserHandle getTabOwnerUserHandleForLaunch() {
246         if (sOverrides.tabOwnerUserHandleForLaunch == null) {
247             return super.getTabOwnerUserHandleForLaunch();
248         }
249         return sOverrides.tabOwnerUserHandleForLaunch;
250     }
251 
252     @Override
createContextAsUser(UserHandle user, int flags)253     public Context createContextAsUser(UserHandle user, int flags) {
254         // return the current context as a work profile doesn't really exist in these tests
255         return getApplicationContext();
256     }
257 
258     @Override
queryDirectShareTargets(ChooserListAdapter adapter, boolean skipAppPredictionService)259     protected void queryDirectShareTargets(ChooserListAdapter adapter,
260             boolean skipAppPredictionService) {
261         if (sOverrides.directShareTargets != null) {
262             Pair<Integer, ServiceResultInfo[]> result =
263                     sOverrides.directShareTargets.apply(this, adapter);
264             sendShortcutManagerShareTargetResults(result.first, result.second);
265             return;
266         }
267         if (sOverrides.onQueryDirectShareTargets != null) {
268             sOverrides.onQueryDirectShareTargets.apply(adapter);
269         }
270         super.queryDirectShareTargets(adapter, skipAppPredictionService);
271     }
272 
273     @Override
isQuietModeEnabled(UserHandle userHandle)274     protected boolean isQuietModeEnabled(UserHandle userHandle) {
275         return sOverrides.isQuietModeEnabled;
276     }
277 
278     @Override
isUserRunning(UserHandle userHandle)279     protected boolean isUserRunning(UserHandle userHandle) {
280         if (userHandle.equals(UserHandle.SYSTEM)) {
281             return super.isUserRunning(userHandle);
282         }
283         return sOverrides.isWorkProfileUserRunning;
284     }
285 
286     @Override
isUserUnlocked(UserHandle userHandle)287     protected boolean isUserUnlocked(UserHandle userHandle) {
288         if (userHandle.equals(UserHandle.SYSTEM)) {
289             return super.isUserUnlocked(userHandle);
290         }
291         return sOverrides.isWorkProfileUserUnlocked;
292     }
293 }
294