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