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