1 /* 2 * Copyright (C) 2016 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.documentsui; 18 19 import static junit.framework.Assert.assertEquals; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.anyString; 24 import static org.mockito.Mockito.doReturn; 25 26 import android.app.ActivityManager; 27 import android.app.LoaderManager; 28 import android.content.ComponentName; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.IntentSender; 33 import android.content.pm.PackageManager; 34 import android.content.res.Resources; 35 import android.net.Uri; 36 import android.os.UserHandle; 37 import android.os.UserManager; 38 import android.test.mock.MockContentResolver; 39 import android.util.Pair; 40 41 import androidx.annotation.Nullable; 42 import androidx.fragment.app.FragmentActivity; 43 44 import com.android.documentsui.AbstractActionHandler.CommonAddons; 45 import com.android.documentsui.base.DocumentInfo; 46 import com.android.documentsui.base.RootInfo; 47 import com.android.documentsui.testing.TestEnv; 48 import com.android.documentsui.testing.TestEventHandler; 49 import com.android.documentsui.testing.TestEventListener; 50 import com.android.documentsui.testing.TestLoaderManager; 51 import com.android.documentsui.testing.TestPackageManager; 52 import com.android.documentsui.testing.TestResources; 53 import com.android.documentsui.testing.TestSupportLoaderManager; 54 55 import org.mockito.Mockito; 56 57 /** 58 * Abstract to avoid having to implement unnecessary Activity stuff. 59 * Instances are created using {@link #create()}. 60 */ 61 public abstract class TestActivity extends AbstractBase { 62 63 public TestResources resources; 64 public TestPackageManager packageMgr; 65 public Intent intent; 66 public RootInfo currentRoot; 67 public UserHandle currentUserHandle; 68 public MockContentResolver contentResolver; 69 public TestLoaderManager loaderManager; 70 public TestSupportLoaderManager supportLoaderManager; 71 public ActivityManager activityManager; 72 public UserManager userManager; 73 74 public TestEventListener<Intent> startActivity; 75 public TestEventListener<Pair<Intent, UserHandle>> startActivityAsUser; 76 public TestEventListener<Intent> startService; 77 public TestEventListener<Pair<IntentSender, Integer>> startIntentSender; 78 public TestEventListener<RootInfo> rootPicked; 79 public TestEventListener<Void> restoreRootAndDirectory; 80 public TestEventListener<Integer> refreshCurrentRootAndDirectory; 81 public TestEventListener<Boolean> setRootsDrawerOpen; 82 public TestEventListener<Boolean> setRootsDrawerLocked; 83 public TestEventListener<Uri> notifyDirectoryNavigated; 84 public TestEventHandler<Void> finishedHandler; 85 create(TestEnv env)86 public static TestActivity create(TestEnv env) { 87 TestActivity activity = Mockito.mock(TestActivity.class, Mockito.CALLS_REAL_METHODS); 88 activity.init(env); 89 return activity; 90 } 91 init(TestEnv env)92 public void init(TestEnv env) { 93 resources = TestResources.create(); 94 packageMgr = TestPackageManager.create(); 95 intent = new Intent(); 96 currentUserHandle = env.userHandle; 97 98 startActivity = new TestEventListener<>(); 99 startActivityAsUser = new TestEventListener<>(); 100 startService = new TestEventListener<>(); 101 startIntentSender = new TestEventListener<>(); 102 rootPicked = new TestEventListener<>(); 103 restoreRootAndDirectory = new TestEventListener<>(); 104 refreshCurrentRootAndDirectory = new TestEventListener<>(); 105 setRootsDrawerOpen = new TestEventListener<>(); 106 setRootsDrawerLocked = new TestEventListener<>(); 107 notifyDirectoryNavigated = new TestEventListener<>(); 108 contentResolver = env.contentResolver; 109 loaderManager = new TestLoaderManager(); 110 supportLoaderManager = new TestSupportLoaderManager(); 111 finishedHandler = new TestEventHandler<>(); 112 113 // Setup some methods which cannot be overridden. 114 try { 115 doReturn(this).when(this).createPackageContextAsUser(anyString(), anyInt(), 116 any()); 117 } catch (PackageManager.NameNotFoundException e) { 118 } 119 } 120 121 @Override getPackageName()122 public final String getPackageName() { 123 return "Banarama"; 124 } 125 126 @Override startActivity(Intent intent)127 public final void startActivity(Intent intent) { 128 startActivity.accept(intent); 129 } 130 131 @Override startActivityAsUser(Intent intent, UserHandle userHandle)132 public final void startActivityAsUser(Intent intent, UserHandle userHandle) { 133 if (userHandle.equals(currentUserHandle)) { 134 startActivity(intent); 135 } else { 136 startActivityAsUser.accept(new Pair<>(intent, userHandle)); 137 } 138 } 139 assertActivityStarted(String expectedAction)140 public final void assertActivityStarted(String expectedAction) { 141 assertEquals(expectedAction, startActivity.getLastValue().getAction()); 142 } 143 assertActivityAsUserStarted(String expectedAction, UserHandle userHandle)144 public final void assertActivityAsUserStarted(String expectedAction, UserHandle userHandle) { 145 Pair<Intent, UserHandle> intentUserHandle = startActivityAsUser.getLastValue(); 146 assertEquals(expectedAction, intentUserHandle.first.getAction()); 147 assertEquals(intentUserHandle.second, userHandle); 148 } 149 150 @Override startService(Intent intent)151 public final ComponentName startService(Intent intent) { 152 startService.accept(intent); 153 return null; 154 } 155 assertServiceStarted(String expectedAction)156 public final void assertServiceStarted(String expectedAction) { 157 assertEquals(expectedAction, startService.getLastValue().getAction()); 158 } 159 160 @Override getIntent()161 public final Intent getIntent() { 162 return intent; 163 } 164 165 @Override getResources()166 public final Resources getResources() { 167 return resources; 168 } 169 170 @Override getPackageManager()171 public final PackageManager getPackageManager() { 172 return packageMgr; 173 } 174 175 @Override startIntentSenderForResult(IntentSender intent, int requestCode, @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags)176 public final void startIntentSenderForResult(IntentSender intent, int requestCode, 177 @Nullable Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags) 178 throws IntentSender.SendIntentException { 179 startIntentSender.accept(new Pair<>(intent, requestCode)); 180 } 181 182 @Override onRootPicked(RootInfo root)183 public final void onRootPicked(RootInfo root) { 184 rootPicked.accept(root); 185 } 186 187 @Override onDocumentPicked(DocumentInfo doc)188 public final void onDocumentPicked(DocumentInfo doc) { 189 throw new UnsupportedOperationException(); 190 } 191 192 @Override notifyDirectoryNavigated(Uri uri)193 public final void notifyDirectoryNavigated(Uri uri) { 194 notifyDirectoryNavigated.accept(uri); 195 } 196 197 @Override restoreRootAndDirectory()198 public final void restoreRootAndDirectory() { 199 restoreRootAndDirectory.accept(null); 200 } 201 202 @Override refreshCurrentRootAndDirectory(int anim)203 public final void refreshCurrentRootAndDirectory(int anim) { 204 refreshCurrentRootAndDirectory.accept(anim); 205 } 206 207 @Override getCurrentRoot()208 public final RootInfo getCurrentRoot() { 209 return currentRoot; 210 } 211 212 @Override setRootsDrawerOpen(boolean open)213 public final void setRootsDrawerOpen(boolean open) { 214 setRootsDrawerOpen.accept(open); 215 } 216 217 @Override setRootsDrawerLocked(boolean locked)218 public final void setRootsDrawerLocked(boolean locked) { 219 setRootsDrawerLocked.accept(locked); 220 } 221 222 @Override getContentResolver()223 public final ContentResolver getContentResolver() { 224 return contentResolver; 225 } 226 227 @Override getApplicationContext()228 public final Context getApplicationContext() { 229 return this; 230 } 231 232 @Override isDestroyed()233 public boolean isDestroyed() { 234 return false; 235 } 236 237 @Override updateNavigator()238 public final void updateNavigator() {} 239 240 @Override getLoaderManager()241 public final LoaderManager getLoaderManager() { 242 return loaderManager; 243 } 244 245 @Override getSupportLoaderManager()246 public final androidx.loader.app.LoaderManager getSupportLoaderManager() { 247 return supportLoaderManager; 248 } 249 250 @Override getSystemService(String service)251 public final Object getSystemService(String service) { 252 switch (service) { 253 case Context.ACTIVITY_SERVICE: 254 return activityManager; 255 case Context.USER_SERVICE: 256 return userManager; 257 } 258 259 throw new IllegalArgumentException("Unknown service " + service); 260 } 261 262 @Override finish()263 public final void finish() { 264 finishedHandler.accept(null); 265 } 266 } 267 268 // Trick Mockito into finding our Addons methods correctly. W/o this 269 // hack, Mockito thinks Addons methods are not implemented. 270 abstract class AbstractBase extends FragmentActivity implements CommonAddons {} 271