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 
getMultiProfilePagerAdapterCount()91     int getMultiProfilePagerAdapterCount(){
92         return mMultiProfilePagerAdapter.getCount();
93     }
94 
95     @Override
isVoiceInteraction()96     public boolean isVoiceInteraction() {
97         if (sOverrides.isVoiceInteraction != null) {
98             return sOverrides.isVoiceInteraction;
99         }
100         return super.isVoiceInteraction();
101     }
102 
103     @Override
safelyStartActivityInternal(TargetInfo cti, UserHandle user, @Nullable Bundle options)104     public void safelyStartActivityInternal(TargetInfo cti, UserHandle user,
105             @Nullable Bundle options) {
106         if (sOverrides.onSafelyStartInternalCallback != null
107                 && sOverrides.onSafelyStartInternalCallback.apply(new Pair<>(cti, user))) {
108             return;
109         }
110         super.safelyStartActivityInternal(cti, user, options);
111     }
112 
113     @Override
createListController(UserHandle userHandle)114     protected ResolverListController createListController(UserHandle userHandle) {
115         if (userHandle == UserHandle.SYSTEM) {
116             when(sOverrides.resolverListController.getUserHandle()).thenReturn(UserHandle.SYSTEM);
117             return sOverrides.resolverListController;
118         }
119         if (isLaunchedInSingleUserMode()) {
120             when(sOverrides.resolverListController.getUserHandle()).thenReturn(userHandle);
121             return sOverrides.resolverListController;
122         }
123         when(sOverrides.workResolverListController.getUserHandle()).thenReturn(userHandle);
124         return sOverrides.workResolverListController;
125     }
126 
127     @Override
getPackageManager()128     public PackageManager getPackageManager() {
129         if (sOverrides.createPackageManager != null) {
130             return sOverrides.createPackageManager.apply(super.getPackageManager());
131         }
132         return super.getPackageManager();
133     }
134 
getCurrentUserHandle()135     protected UserHandle getCurrentUserHandle() {
136         return mMultiProfilePagerAdapter.getCurrentUserHandle();
137     }
138 
139     @Override
getPersonalProfileUserHandle()140     protected UserHandle getPersonalProfileUserHandle() {
141         return super.getPersonalProfileUserHandle();
142     }
143 
144     @Override
getWorkProfileUserHandle()145     protected UserHandle getWorkProfileUserHandle() {
146         return sOverrides.workProfileUserHandle;
147     }
148 
149     @Override
getCloneProfileUserHandle()150     protected UserHandle getCloneProfileUserHandle() {
151         return sOverrides.cloneProfileUserHandle;
152     }
153 
154     @Override
getPrivateProfileUserHandle()155     protected UserHandle getPrivateProfileUserHandle() {
156         return sOverrides.privateProfileUserHandle;
157     }
158 
159     @Override
getTabOwnerUserHandleForLaunch()160     protected UserHandle getTabOwnerUserHandleForLaunch() {
161         if (sOverrides.tabOwnerUserHandleForLaunch == null) {
162             return super.getTabOwnerUserHandleForLaunch();
163         }
164         return sOverrides.tabOwnerUserHandleForLaunch;
165     }
166 
167     @Override
startActivityAsUser(Intent intent, Bundle options, UserHandle user)168     public void startActivityAsUser(Intent intent, Bundle options, UserHandle user) {
169         super.startActivityAsUser(intent, options, user);
170     }
171 
172     @Override
getResolverRankerServiceUserHandleListInternal(UserHandle userHandle)173     protected List<UserHandle> getResolverRankerServiceUserHandleListInternal(UserHandle
174             userHandle) {
175         return super.getResolverRankerServiceUserHandleListInternal(userHandle);
176     }
177 
178     /**
179      * We cannot directly mock the activity created since instrumentation creates it.
180      * <p>
181      * Instead, we use static instances of this object to modify behavior.
182      */
183     static class OverrideData {
184         @SuppressWarnings("Since15")
185         public Function<PackageManager, PackageManager> createPackageManager;
186         public Function<Pair<TargetInfo, UserHandle>, Boolean> onSafelyStartInternalCallback;
187         public ResolverListController resolverListController;
188         public ResolverListController workResolverListController;
189         public Boolean isVoiceInteraction;
190         public UserHandle workProfileUserHandle;
191         public UserHandle cloneProfileUserHandle;
192         public UserHandle privateProfileUserHandle;
193         public UserHandle tabOwnerUserHandleForLaunch;
194         public Integer myUserId;
195         public boolean hasCrossProfileIntents;
196         public boolean isQuietModeEnabled;
197         public QuietModeManager mQuietModeManager;
198         public CrossProfileIntentsChecker mCrossProfileIntentsChecker;
199 
reset()200         public void reset() {
201             onSafelyStartInternalCallback = null;
202             isVoiceInteraction = null;
203             createPackageManager = null;
204             resolverListController = mock(ResolverListController.class);
205             workResolverListController = mock(ResolverListController.class);
206             workProfileUserHandle = null;
207             cloneProfileUserHandle = null;
208             privateProfileUserHandle = null;
209             tabOwnerUserHandleForLaunch = null;
210             myUserId = null;
211             hasCrossProfileIntents = true;
212             isQuietModeEnabled = false;
213 
214             mQuietModeManager = new QuietModeManager() {
215                 @Override
216                 public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) {
217                     return isQuietModeEnabled;
218                 }
219 
220                 @Override
221                 public void requestQuietModeEnabled(boolean enabled,
222                         UserHandle workProfileUserHandle) {
223                     isQuietModeEnabled = enabled;
224                 }
225 
226                 @Override
227                 public void markWorkProfileEnabledBroadcastReceived() {
228                 }
229 
230                 @Override
231                 public boolean isWaitingToEnableWorkProfile() {
232                     return false;
233                 }
234             };
235 
236             mCrossProfileIntentsChecker = mock(CrossProfileIntentsChecker.class);
237             when(mCrossProfileIntentsChecker.hasCrossProfileIntents(any(), anyInt(), anyInt()))
238                     .thenAnswer(invocation -> hasCrossProfileIntents);
239         }
240     }
241 }
242