1 /*
2  * Copyright (C) 2017 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.ArgumentMatchers.any;
20 import static org.mockito.ArgumentMatchers.anyInt;
21 import static org.mockito.Mockito.mock;
22 import static org.mockito.Mockito.when;
23 
24 import android.annotation.Nullable;
25 import android.app.usage.UsageStatsManager;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ResolveInfo;
30 import android.os.Bundle;
31 import android.os.UserHandle;
32 import android.util.Pair;
33 
34 import com.android.internal.app.AbstractMultiProfilePagerAdapter.CrossProfileIntentsChecker;
35 import com.android.internal.app.AbstractMultiProfilePagerAdapter.QuietModeManager;
36 import com.android.internal.app.chooser.TargetInfo;
37 
38 import java.util.List;
39 import java.util.function.Function;
40 
41 /*
42  * Simple wrapper around chooser activity to be able to initiate it under test
43  */
44 public class ResolverWrapperActivity extends ResolverActivity {
45     static final OverrideData sOverrides = new OverrideData();
46     private UsageStatsManager mUsm;
47 
ResolverWrapperActivity()48     public ResolverWrapperActivity() {
49         super(/* isIntentPicker= */ true);
50     }
51 
52     @Override
createResolverListAdapter(Context context, List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed, UserHandle userHandle)53     public ResolverListAdapter createResolverListAdapter(Context context,
54             List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList,
55             boolean filterLastUsed, UserHandle userHandle) {
56         return new ResolverWrapperAdapter(context, payloadIntents, initialIntents, rList,
57                 filterLastUsed, createListController(userHandle), this, userHandle);
58     }
59 
60     @Override
createCrossProfileIntentsChecker()61     protected CrossProfileIntentsChecker createCrossProfileIntentsChecker() {
62         if (sOverrides.mCrossProfileIntentsChecker != null) {
63             return sOverrides.mCrossProfileIntentsChecker;
64         }
65         return super.createCrossProfileIntentsChecker();
66     }
67 
68     @Override
createQuietModeManager()69     protected QuietModeManager createQuietModeManager() {
70         if (sOverrides.mQuietModeManager != null) {
71             return sOverrides.mQuietModeManager;
72         }
73         return super.createQuietModeManager();
74     }
75 
getAdapter()76     ResolverWrapperAdapter getAdapter() {
77         return (ResolverWrapperAdapter) mMultiProfilePagerAdapter.getActiveListAdapter();
78     }
79 
getPersonalListAdapter()80     ResolverListAdapter getPersonalListAdapter() {
81         return ((ResolverListAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(0));
82     }
83 
getWorkListAdapter()84     ResolverListAdapter getWorkListAdapter() {
85         if (mMultiProfilePagerAdapter.getInactiveListAdapter() == null) {
86             return null;
87         }
88         return ((ResolverListAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(1));
89     }
90 
91     @Override
isVoiceInteraction()92     public boolean isVoiceInteraction() {
93         if (sOverrides.isVoiceInteraction != null) {
94             return sOverrides.isVoiceInteraction;
95         }
96         return super.isVoiceInteraction();
97     }
98 
99     @Override
safelyStartActivityInternal(TargetInfo cti, UserHandle user, @Nullable Bundle options)100     public void safelyStartActivityInternal(TargetInfo cti, UserHandle user,
101             @Nullable Bundle options) {
102         if (sOverrides.onSafelyStartInternalCallback != null
103                 && sOverrides.onSafelyStartInternalCallback.apply(new Pair<>(cti, user))) {
104             return;
105         }
106         super.safelyStartActivityInternal(cti, user, options);
107     }
108 
109     @Override
createListController(UserHandle userHandle)110     protected ResolverListController createListController(UserHandle userHandle) {
111         if (userHandle == UserHandle.SYSTEM) {
112             when(sOverrides.resolverListController.getUserHandle()).thenReturn(UserHandle.SYSTEM);
113             return sOverrides.resolverListController;
114         }
115         when(sOverrides.workResolverListController.getUserHandle()).thenReturn(userHandle);
116         return sOverrides.workResolverListController;
117     }
118 
119     @Override
getPackageManager()120     public PackageManager getPackageManager() {
121         if (sOverrides.createPackageManager != null) {
122             return sOverrides.createPackageManager.apply(super.getPackageManager());
123         }
124         return super.getPackageManager();
125     }
126 
getCurrentUserHandle()127     protected UserHandle getCurrentUserHandle() {
128         return mMultiProfilePagerAdapter.getCurrentUserHandle();
129     }
130 
131     @Override
getPersonalProfileUserHandle()132     protected UserHandle getPersonalProfileUserHandle() {
133         return super.getPersonalProfileUserHandle();
134     }
135 
136     @Override
getWorkProfileUserHandle()137     protected UserHandle getWorkProfileUserHandle() {
138         return sOverrides.workProfileUserHandle;
139     }
140 
141     @Override
getCloneProfileUserHandle()142     protected UserHandle getCloneProfileUserHandle() {
143         return sOverrides.cloneProfileUserHandle;
144     }
145 
146     @Override
getTabOwnerUserHandleForLaunch()147     protected UserHandle getTabOwnerUserHandleForLaunch() {
148         if (sOverrides.tabOwnerUserHandleForLaunch == null) {
149             return super.getTabOwnerUserHandleForLaunch();
150         }
151         return sOverrides.tabOwnerUserHandleForLaunch;
152     }
153 
154     @Override
startActivityAsUser(Intent intent, Bundle options, UserHandle user)155     public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
156         super.startActivityAsUser(intent, options, user);
157     }
158 
159     @Override
getResolverRankerServiceUserHandleListInternal(UserHandle userHandle)160     protected List<UserHandle> getResolverRankerServiceUserHandleListInternal(UserHandle
161             userHandle) {
162         return super.getResolverRankerServiceUserHandleListInternal(userHandle);
163     }
164 
165     /**
166      * We cannot directly mock the activity created since instrumentation creates it.
167      * <p>
168      * Instead, we use static instances of this object to modify behavior.
169      */
170     static class OverrideData {
171         @SuppressWarnings("Since15")
172         public Function<PackageManager, PackageManager> createPackageManager;
173         public Function<Pair<TargetInfo, UserHandle>, Boolean> onSafelyStartInternalCallback;
174         public ResolverListController resolverListController;
175         public ResolverListController workResolverListController;
176         public Boolean isVoiceInteraction;
177         public UserHandle workProfileUserHandle;
178         public UserHandle cloneProfileUserHandle;
179         public UserHandle tabOwnerUserHandleForLaunch;
180         public Integer myUserId;
181         public boolean hasCrossProfileIntents;
182         public boolean isQuietModeEnabled;
183         public QuietModeManager mQuietModeManager;
184         public CrossProfileIntentsChecker mCrossProfileIntentsChecker;
185 
reset()186         public void reset() {
187             onSafelyStartInternalCallback = null;
188             isVoiceInteraction = null;
189             createPackageManager = null;
190             resolverListController = mock(ResolverListController.class);
191             workResolverListController = mock(ResolverListController.class);
192             workProfileUserHandle = null;
193             cloneProfileUserHandle = null;
194             tabOwnerUserHandleForLaunch = null;
195             myUserId = null;
196             hasCrossProfileIntents = true;
197             isQuietModeEnabled = false;
198 
199             mQuietModeManager = new QuietModeManager() {
200                 @Override
201                 public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) {
202                     return isQuietModeEnabled;
203                 }
204 
205                 @Override
206                 public void requestQuietModeEnabled(boolean enabled,
207                         UserHandle workProfileUserHandle) {
208                     isQuietModeEnabled = enabled;
209                 }
210 
211                 @Override
212                 public void markWorkProfileEnabledBroadcastReceived() {
213                 }
214 
215                 @Override
216                 public boolean isWaitingToEnableWorkProfile() {
217                     return false;
218                 }
219             };
220 
221             mCrossProfileIntentsChecker = mock(CrossProfileIntentsChecker.class);
222             when(mCrossProfileIntentsChecker.hasCrossProfileIntents(any(), anyInt(), anyInt()))
223                     .thenAnswer(invocation -> hasCrossProfileIntents);
224         }
225     }
226 }
227