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