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.mock; 20 import static org.mockito.Mockito.when; 21 22 import android.annotation.Nullable; 23 import android.app.usage.UsageStatsManager; 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.UserHandle; 34 import android.util.Size; 35 36 import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter; 37 import com.android.internal.app.chooser.DisplayResolveInfo; 38 import com.android.internal.app.chooser.TargetInfo; 39 import com.android.internal.logging.MetricsLogger; 40 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 41 42 import java.util.List; 43 import java.util.function.Function; 44 45 public class ChooserWrapperActivity extends ChooserActivity { 46 /* 47 * Simple wrapper around chooser activity to be able to initiate it under test 48 */ 49 static final OverrideData sOverrides = new OverrideData(); 50 private UsageStatsManager mUsm; 51 52 @Override createMultiProfilePagerAdapter( Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed)53 protected AbstractMultiProfilePagerAdapter createMultiProfilePagerAdapter( 54 Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed) { 55 AbstractMultiProfilePagerAdapter multiProfilePagerAdapter = 56 super.createMultiProfilePagerAdapter(initialIntents, rList, filterLastUsed); 57 multiProfilePagerAdapter.setInjector(sOverrides.multiPagerAdapterInjector); 58 return multiProfilePagerAdapter; 59 } 60 61 @Override createChooserListAdapter(Context context, List<Intent> payloadIntents, Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed, ResolverListController resolverListController)62 public ChooserListAdapter createChooserListAdapter(Context context, List<Intent> payloadIntents, 63 Intent[] initialIntents, List<ResolveInfo> rList, boolean filterLastUsed, 64 ResolverListController resolverListController) { 65 PackageManager packageManager = 66 sOverrides.packageManager == null ? context.getPackageManager() 67 : sOverrides.packageManager; 68 return new ChooserListAdapter(context, payloadIntents, initialIntents, rList, 69 filterLastUsed, resolverListController, 70 this, this, packageManager); 71 } 72 getAdapter()73 ChooserListAdapter getAdapter() { 74 return mChooserMultiProfilePagerAdapter.getActiveListAdapter(); 75 } 76 getPersonalListAdapter()77 ChooserListAdapter getPersonalListAdapter() { 78 return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(0)) 79 .getListAdapter(); 80 } 81 getWorkListAdapter()82 ChooserListAdapter getWorkListAdapter() { 83 if (mMultiProfilePagerAdapter.getInactiveListAdapter() == null) { 84 return null; 85 } 86 return ((ChooserGridAdapter) mMultiProfilePagerAdapter.getAdapterForIndex(1)) 87 .getListAdapter(); 88 } 89 getIsSelected()90 boolean getIsSelected() { return mIsSuccessfullySelected; } 91 getUsageStatsManager()92 UsageStatsManager getUsageStatsManager() { 93 if (mUsm == null) { 94 mUsm = (UsageStatsManager) getSystemService(Context.USAGE_STATS_SERVICE); 95 } 96 return mUsm; 97 } 98 99 @Override isVoiceInteraction()100 public boolean isVoiceInteraction() { 101 if (sOverrides.isVoiceInteraction != null) { 102 return sOverrides.isVoiceInteraction; 103 } 104 return super.isVoiceInteraction(); 105 } 106 107 @Override safelyStartActivity(com.android.internal.app.chooser.TargetInfo cti)108 public void safelyStartActivity(com.android.internal.app.chooser.TargetInfo cti) { 109 if (sOverrides.onSafelyStartCallback != null && 110 sOverrides.onSafelyStartCallback.apply(cti)) { 111 return; 112 } 113 super.safelyStartActivity(cti); 114 } 115 116 @Override createListController(UserHandle userHandle)117 protected ResolverListController createListController(UserHandle userHandle) { 118 if (userHandle == UserHandle.SYSTEM) { 119 when(sOverrides.resolverListController.getUserHandle()).thenReturn(UserHandle.SYSTEM); 120 return sOverrides.resolverListController; 121 } 122 when(sOverrides.workResolverListController.getUserHandle()).thenReturn(userHandle); 123 return sOverrides.workResolverListController; 124 } 125 126 @Override getPackageManager()127 public PackageManager getPackageManager() { 128 if (sOverrides.createPackageManager != null) { 129 return sOverrides.createPackageManager.apply(super.getPackageManager()); 130 } 131 return super.getPackageManager(); 132 } 133 134 @Override getResources()135 public Resources getResources() { 136 if (sOverrides.resources != null) { 137 return sOverrides.resources; 138 } 139 return super.getResources(); 140 } 141 142 @Override loadThumbnail(Uri uri, Size size)143 protected Bitmap loadThumbnail(Uri uri, Size size) { 144 if (sOverrides.previewThumbnail != null) { 145 return sOverrides.previewThumbnail; 146 } 147 return super.loadThumbnail(uri, size); 148 } 149 150 @Override isImageType(String mimeType)151 protected boolean isImageType(String mimeType) { 152 return sOverrides.isImageType; 153 } 154 155 @Override getMetricsLogger()156 protected MetricsLogger getMetricsLogger() { 157 return sOverrides.metricsLogger; 158 } 159 160 @Override getChooserActivityLogger()161 protected ChooserActivityLogger getChooserActivityLogger() { 162 return sOverrides.chooserActivityLogger; 163 } 164 165 @Override queryResolver(ContentResolver resolver, Uri uri)166 public Cursor queryResolver(ContentResolver resolver, Uri uri) { 167 if (sOverrides.resolverCursor != null) { 168 return sOverrides.resolverCursor; 169 } 170 171 if (sOverrides.resolverForceException) { 172 throw new SecurityException("Test exception handling"); 173 } 174 175 return super.queryResolver(resolver, uri); 176 } 177 178 @Override isWorkProfile()179 protected boolean isWorkProfile() { 180 if (sOverrides.alternateProfileSetting != 0) { 181 return sOverrides.alternateProfileSetting == MetricsEvent.MANAGED_PROFILE; 182 } 183 return super.isWorkProfile(); 184 } 185 createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri, CharSequence pLabel, CharSequence pInfo, Intent replacementIntent, @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter)186 public DisplayResolveInfo createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri, 187 CharSequence pLabel, CharSequence pInfo, Intent replacementIntent, 188 @Nullable ResolveInfoPresentationGetter resolveInfoPresentationGetter) { 189 return new DisplayResolveInfo(originalIntent, pri, pLabel, pInfo, replacementIntent, 190 resolveInfoPresentationGetter); 191 } 192 193 @Override getWorkProfileUserHandle()194 protected UserHandle getWorkProfileUserHandle() { 195 return sOverrides.workProfileUserHandle; 196 } 197 getCurrentUserHandle()198 protected UserHandle getCurrentUserHandle() { 199 return mMultiProfilePagerAdapter.getCurrentUserHandle(); 200 } 201 202 @Override createContextAsUser(UserHandle user, int flags)203 public Context createContextAsUser(UserHandle user, int flags) { 204 // return the current context as a work profile doesn't really exist in these tests 205 return getApplicationContext(); 206 } 207 208 @Override queryDirectShareTargets(ChooserListAdapter adapter, boolean skipAppPredictionService)209 protected void queryDirectShareTargets(ChooserListAdapter adapter, 210 boolean skipAppPredictionService) { 211 if (sOverrides.onQueryDirectShareTargets != null) { 212 sOverrides.onQueryDirectShareTargets.apply(adapter); 213 } 214 super.queryDirectShareTargets(adapter, skipAppPredictionService); 215 } 216 217 @Override queryTargetServices(ChooserListAdapter adapter)218 protected void queryTargetServices(ChooserListAdapter adapter) { 219 if (sOverrides.onQueryTargetServices != null) { 220 sOverrides.onQueryTargetServices.apply(adapter); 221 } 222 super.queryTargetServices(adapter); 223 } 224 225 @Override isQuietModeEnabled(UserHandle userHandle)226 protected boolean isQuietModeEnabled(UserHandle userHandle) { 227 return sOverrides.isQuietModeEnabled; 228 } 229 230 @Override isUserRunning(UserHandle userHandle)231 protected boolean isUserRunning(UserHandle userHandle) { 232 if (userHandle.equals(UserHandle.SYSTEM)) { 233 return super.isUserRunning(userHandle); 234 } 235 return sOverrides.isWorkProfileUserRunning; 236 } 237 238 @Override isUserUnlocked(UserHandle userHandle)239 protected boolean isUserUnlocked(UserHandle userHandle) { 240 if (userHandle.equals(UserHandle.SYSTEM)) { 241 return super.isUserUnlocked(userHandle); 242 } 243 return sOverrides.isWorkProfileUserUnlocked; 244 } 245 246 /** 247 * We cannot directly mock the activity created since instrumentation creates it. 248 * <p> 249 * Instead, we use static instances of this object to modify behavior. 250 */ 251 static class OverrideData { 252 @SuppressWarnings("Since15") 253 public Function<PackageManager, PackageManager> createPackageManager; 254 public Function<TargetInfo, Boolean> onSafelyStartCallback; 255 public Function<ChooserListAdapter, Void> onQueryDirectShareTargets; 256 public Function<ChooserListAdapter, Void> onQueryTargetServices; 257 public ResolverListController resolverListController; 258 public ResolverListController workResolverListController; 259 public Boolean isVoiceInteraction; 260 public boolean isImageType; 261 public Cursor resolverCursor; 262 public boolean resolverForceException; 263 public Bitmap previewThumbnail; 264 public MetricsLogger metricsLogger; 265 public ChooserActivityLogger chooserActivityLogger; 266 public int alternateProfileSetting; 267 public Resources resources; 268 public UserHandle workProfileUserHandle; 269 public boolean hasCrossProfileIntents; 270 public boolean isQuietModeEnabled; 271 public boolean isWorkProfileUserRunning; 272 public boolean isWorkProfileUserUnlocked; 273 public AbstractMultiProfilePagerAdapter.Injector multiPagerAdapterInjector; 274 public PackageManager packageManager; 275 reset()276 public void reset() { 277 onSafelyStartCallback = null; 278 onQueryDirectShareTargets = null; 279 onQueryTargetServices = null; 280 isVoiceInteraction = null; 281 createPackageManager = null; 282 previewThumbnail = null; 283 isImageType = false; 284 resolverCursor = null; 285 resolverForceException = false; 286 resolverListController = mock(ResolverListController.class); 287 workResolverListController = mock(ResolverListController.class); 288 metricsLogger = mock(MetricsLogger.class); 289 chooserActivityLogger = new ChooserActivityLoggerFake(); 290 alternateProfileSetting = 0; 291 resources = null; 292 workProfileUserHandle = null; 293 hasCrossProfileIntents = true; 294 isQuietModeEnabled = false; 295 isWorkProfileUserRunning = true; 296 isWorkProfileUserUnlocked = true; 297 packageManager = null; 298 multiPagerAdapterInjector = new AbstractMultiProfilePagerAdapter.Injector() { 299 @Override 300 public boolean hasCrossProfileIntents(List<Intent> intents, int sourceUserId, 301 int targetUserId) { 302 return hasCrossProfileIntents; 303 } 304 305 @Override 306 public boolean isQuietModeEnabled(UserHandle workProfileUserHandle) { 307 return isQuietModeEnabled; 308 } 309 310 @Override 311 public void requestQuietModeEnabled(boolean enabled, 312 UserHandle workProfileUserHandle) { 313 isQuietModeEnabled = enabled; 314 } 315 }; 316 } 317 } 318 } 319