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 android.autofillservice.cts.commontests;
18 
19 import static android.autofillservice.cts.testcore.Helper.DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS;
20 import static android.autofillservice.cts.testcore.Helper.getContext;
21 import static android.autofillservice.cts.testcore.InstrumentedAutoFillService.SERVICE_NAME;
22 import static android.content.Context.CLIPBOARD_SERVICE;
23 
24 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
25 
26 import static com.android.compatibility.common.util.ShellUtils.runShellCommand;
27 
28 import static org.junit.Assume.assumeFalse;
29 
30 import android.app.PendingIntent;
31 import android.autofillservice.cts.R;
32 import android.autofillservice.cts.activities.AbstractAutoFillActivity;
33 import android.autofillservice.cts.activities.AugmentedAuthActivity;
34 import android.autofillservice.cts.activities.AuthenticationActivity;
35 import android.autofillservice.cts.activities.LoginActivity;
36 import android.autofillservice.cts.activities.LoginImportantForCredentialManagerActivity;
37 import android.autofillservice.cts.activities.LoginMixedImportantForCredentialManagerActivity;
38 import android.autofillservice.cts.activities.PreSimpleSaveActivity;
39 import android.autofillservice.cts.activities.SimpleSaveActivity;
40 import android.autofillservice.cts.testcore.AutofillActivityTestRule;
41 import android.autofillservice.cts.testcore.AutofillLoggingTestRule;
42 import android.autofillservice.cts.testcore.AutofillTestWatcher;
43 import android.autofillservice.cts.testcore.Helper;
44 import android.autofillservice.cts.testcore.InlineUiBot;
45 import android.autofillservice.cts.testcore.InstrumentedAutoFillService;
46 import android.autofillservice.cts.testcore.InstrumentedAutoFillService.Replier;
47 import android.autofillservice.cts.testcore.UiBot;
48 import android.content.ClipboardManager;
49 import android.content.Context;
50 import android.content.Intent;
51 import android.content.pm.PackageManager;
52 import android.provider.DeviceConfig;
53 import android.provider.Settings;
54 import android.service.autofill.InlinePresentation;
55 import android.util.Log;
56 import android.view.autofill.AutofillFeatureFlags;
57 import android.view.autofill.AutofillManager;
58 import android.widget.RemoteViews;
59 
60 import androidx.annotation.NonNull;
61 import androidx.test.InstrumentationRegistry;
62 import androidx.test.ext.junit.runners.AndroidJUnit4;
63 
64 import com.android.compatibility.common.util.DeviceConfigStateChangerRule;
65 import com.android.compatibility.common.util.DisableAnimationRule;
66 import com.android.compatibility.common.util.RequiredFeatureRule;
67 import com.android.compatibility.common.util.RetryRule;
68 import com.android.compatibility.common.util.SafeCleanerRule;
69 import com.android.compatibility.common.util.SettingsStateKeeperRule;
70 import com.android.compatibility.common.util.TestNameUtils;
71 import com.android.cts.mockime.ImeSettings;
72 import com.android.cts.mockime.MockImeSessionRule;
73 
74 import org.junit.AfterClass;
75 import org.junit.Before;
76 import org.junit.BeforeClass;
77 import org.junit.ClassRule;
78 import org.junit.Rule;
79 import org.junit.rules.RuleChain;
80 import org.junit.rules.TestRule;
81 import org.junit.runner.Description;
82 import org.junit.runner.RunWith;
83 import org.junit.runners.model.Statement;
84 
85 /**
86  * Placeholder for the base class for all integration tests:
87  *
88  * <ul>
89  *   <li>{@link AutoActivityLaunch}
90  *   <li>{@link ManualActivityLaunch}
91  * </ul>
92  *
93  * <p>These classes provide the common infrastructure such as:
94  *
95  * <ul>
96  *   <li>Preserving the autofill service settings.
97  *   <li>Cleaning up test state.
98  *   <li>Wrapping the test under autofill-specific test rules.
99  *   <li>Launching the activity used by the test.
100  * </ul>
101  */
102 public final class AutoFillServiceTestCase {
103 
104     /**
105      * Base class for all test cases that use an {@link AutofillActivityTestRule} to
106      * launch the activity.
107      */
108     // Must be public because of @ClassRule
109     public abstract static class AutoActivityLaunch<A extends AbstractAutoFillActivity>
110             extends BaseTestCase {
111 
112         /**
113          * Returns if inline suggestion is enabled.
114          */
isInlineMode()115         protected boolean isInlineMode() {
116             return false;
117         }
118 
getInlineUiBot()119         protected static InlineUiBot getInlineUiBot() {
120             return new InlineUiBot(getContext());
121         }
122 
getDropdownUiBot()123         protected static UiBot getDropdownUiBot() {
124             return sDefaultUiBot;
125         }
126 
127         @ClassRule
128         public static final SettingsStateKeeperRule sPublicServiceSettingsKeeper =
129                 sTheRealServiceSettingsKeeper;
130 
AutoActivityLaunch()131         protected AutoActivityLaunch() {
132             super(sDefaultUiBot);
133         }
AutoActivityLaunch(UiBot uiBot)134         protected AutoActivityLaunch(UiBot uiBot) {
135             super(uiBot);
136         }
137 
138         @Override
getMainTestRule()139         protected TestRule getMainTestRule() {
140             // Tries to set the orientation, noop if nothing happens
141             getDropdownUiBot().maybeSetScreenOrientation(UiBot.PORTRAIT);
142             return getActivityRule();
143         }
144 
145         /**
146          * Gets the rule to launch the main activity for this test.
147          *
148          * <p><b>Note: </b>the rule must be either lazily generated or a static singleton, otherwise
149          * this method could return {@code null} when the rule chain that uses it is constructed.
150          *
151          */
getActivityRule()152         protected abstract @NonNull AutofillActivityTestRule<A> getActivityRule();
153 
launchActivity(@onNull Intent intent)154         protected @NonNull A launchActivity(@NonNull Intent intent) {
155             return getActivityRule().launchActivity(intent);
156         }
157 
getActivity()158         protected @NonNull A getActivity() {
159             return getActivityRule().getActivity();
160         }
161     }
162 
163     /**
164      * Base class for all test cases that don't require an {@link AutofillActivityTestRule}.
165      */
166     // Must be public because of @ClassRule
167     public abstract static class ManualActivityLaunch extends BaseTestCase {
168 
169         @ClassRule
170         public static final SettingsStateKeeperRule sPublicServiceSettingsKeeper =
171                 sTheRealServiceSettingsKeeper;
172 
ManualActivityLaunch()173         protected ManualActivityLaunch() {
174             this(sDefaultUiBot);
175         }
176 
ManualActivityLaunch(@onNull UiBot uiBot)177         protected ManualActivityLaunch(@NonNull UiBot uiBot) {
178             super(uiBot);
179         }
180 
181         @Override
getMainTestRule()182         protected TestRule getMainTestRule() {
183             // TODO: create a NoOpTestRule on common code
184             return new TestRule() {
185 
186                 @Override
187                 public Statement apply(Statement base, Description description) {
188                     // Returns a no-op statements
189                     return new Statement() {
190                         @Override
191                         public void evaluate() throws Throwable {
192                             base.evaluate();
193                         }
194                     };
195                 }
196             };
197         }
198 
199         protected SimpleSaveActivity startSimpleSaveActivity() throws Exception {
200             final Intent intent = new Intent(mContext, SimpleSaveActivity.class)
201                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
202             mContext.startActivity(intent);
203             mUiBot.assertShownByRelativeId(SimpleSaveActivity.ID_LABEL);
204             return SimpleSaveActivity.getInstance();
205         }
206 
207         protected PreSimpleSaveActivity startPreSimpleSaveActivity() throws Exception {
208             final Intent intent = new Intent(mContext, PreSimpleSaveActivity.class)
209                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
210             mContext.startActivity(intent);
211             mUiBot.assertShownByRelativeId(PreSimpleSaveActivity.ID_PRE_LABEL);
212             return PreSimpleSaveActivity.getInstance();
213         }
214 
215         protected LoginActivity startLoginActivity() throws Exception {
216             final Intent intent = new Intent(mContext, LoginActivity.class)
217                     .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
218             mContext.startActivity(intent);
219             mUiBot.assertShownByRelativeId(Helper.ID_USERNAME_LABEL);
220             return LoginActivity.getCurrentActivity();
221         }
222 
223         protected LoginImportantForCredentialManagerActivity
224                     startLoginImportantForCredentialManagerActivity(boolean useAutofillHint)
225                 throws Exception {
226             final Intent intent =
227                     new Intent(mContext, LoginImportantForCredentialManagerActivity.class)
228                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
229                         .putExtra("useAutofillHint", useAutofillHint);
230             mContext.startActivity(intent);
231             mUiBot.assertShownByRelativeId(Helper.ID_USERNAME_LABEL);
232             return LoginImportantForCredentialManagerActivity.getCurrentActivity();
233         }
234 
235         protected LoginMixedImportantForCredentialManagerActivity
236                 startLoginMixedImportantForCredentialManagerActivity(boolean useAutofillHInt)
237                 throws Exception {
238             final Intent intent =
239                     new Intent(mContext, LoginMixedImportantForCredentialManagerActivity.class)
240                         .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
241                         .putExtra("useAutofillHint", useAutofillHInt);
242             mContext.startActivity(intent);
243             mUiBot.assertShownByRelativeId(Helper.ID_USERNAME_LABEL);
244             return LoginMixedImportantForCredentialManagerActivity.getCurrentActivity();
245         }
246     }
247 
248     @RunWith(AndroidJUnit4.class)
249     // Must be public because of @ClassRule
250     public abstract static class BaseTestCase {
251 
252         private static final String TAG = "AutoFillServiceTestCase";
253 
254         protected static final Replier sReplier = InstrumentedAutoFillService.getReplier();
255 
256         protected static final Context sContext = getInstrumentation().getTargetContext();
257 
258         // Hack because JUnit requires that @ClassRule instance belong to a public class.
259         protected static final SettingsStateKeeperRule sTheRealServiceSettingsKeeper =
260                 new SettingsStateKeeperRule(sContext, Settings.Secure.AUTOFILL_SERVICE) {
261             @Override
262             protected void preEvaluate(Description description) {
263                 TestNameUtils.setCurrentTestClass(description.getClassName());
264             }
265 
266             @Override
267             protected void postEvaluate(Description description) {
268                 TestNameUtils.setCurrentTestClass(null);
269             }
270         };
271 
272         public static final MockImeSessionRule sMockImeSessionRule = new MockImeSessionRule(
273                 InstrumentationRegistry.getTargetContext(),
274                 InstrumentationRegistry.getInstrumentation().getUiAutomation(),
275                 new ImeSettings.Builder().setInlineSuggestionsEnabled(true)
276                         .setInlineSuggestionViewContentDesc(InlineUiBot.SUGGESTION_STRIP_DESC));
277 
278         private final AutofillTestWatcher mTestWatcher = new AutofillTestWatcher();
279 
280         private final RetryRule mRetryRule =
281                 new RetryRule(getNumberRetries(), () -> {
282                     // Between testing and retries, clean all launched activities to avoid
283                     // exception:
284                     //     Could not launch intent Intent { ... } within 45 seconds.
285                     mTestWatcher.cleanAllActivities();
286                     cleanAllActivities();
287                 });
288 
289         private final AutofillLoggingTestRule mLoggingRule = new AutofillLoggingTestRule(TAG);
290 
291         protected final SafeCleanerRule mSafeCleanerRule = new SafeCleanerRule()
292                 .setDumper(mLoggingRule)
293                 .run(() -> sReplier.assertNoUnhandledFillRequests())
294                 .run(() -> sReplier.assertNoUnhandledSaveRequests())
295                 .add(() -> {
296                     return sReplier.getExceptions();
297                 });
298 
299         /**
300          * Disable animation for UiAutomator because animation will cause the UiAutomator
301          * got a wrong position and then tests failed due to click on the wrong position.
302          *
303          * This is annotated as @ClassRule instead of @Rule, to save time of disabling and
304          * re-enabling animation for each test method.
305          */
306         @ClassRule
307         public static DisableAnimationRule sDisableAnimationRule = new DisableAnimationRule();
308 
309         @Rule
310         public final RuleChain mLookAllTheseRules = RuleChain
311                 //
312                 // requiredFeatureRule should be first so the test can be skipped right away
313                 .outerRule(getRequiredFeaturesRule())
314                 //
315                 // mTestWatcher should always be one the first rules, as it defines the name of the
316                 // test being ran and finishes dangling activities at the end
317                 .around(mTestWatcher)
318                 //
319                 // sMockImeSessionRule make sure MockImeSession.create() is used to launch mock IME
320                 .around(sMockImeSessionRule)
321                 //
322                 // mLoggingRule wraps the test but doesn't interfere with it
323                 .around(mLoggingRule)
324                 //
325                 // mSafeCleanerRule will catch errors
326                 .around(mSafeCleanerRule)
327                 //
328                 // mRetryRule should be closest to the main test as possible
329                 .around(mRetryRule)
330                 //
331                 // Augmented Autofill should be disabled by default
332                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
333                         AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_SMART_SUGGESTION_SUPPORTED_MODES,
334                         Integer.toString(getSmartSuggestionMode())))
335                 //
336                 // Fill Dialog should be disabled by default
337                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
338                         AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_DIALOG_ENABLED,
339                         Boolean.toString(false)))
340                 //
341                 // Hints list of Fill Dialog should be empty by default
342                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
343                         DEVICE_CONFIG_AUTOFILL_DIALOG_HINTS,
344                         ""))
345 
346                 //
347                 // CredentialManager-Autofill integration enabled by default
348                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
349                         AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_ENABLED,
350                         Boolean.toString(true)))
351                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
352                         AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_CREDENTIAL_MANAGER_IGNORE_VIEWS,
353                         Boolean.toString(true)))
354 
355                 //
356                 // PCC Detection should be off by default
357                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
358                         AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_PCC_CLASSIFICATION_ENABLED,
359                         Boolean.toString(false)))
360 
361                 //
362                 // PCC Detection Hints should be empty by default
363                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
364                         AutofillFeatureFlags.DEVICE_CONFIG_AUTOFILL_PCC_FEATURE_PROVIDER_HINTS,
365                         ""))
366 
367 
368                 //
369                 // AFAA should be off by default
370                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
371                             AutofillFeatureFlags.
372                                 DEVICE_CONFIG_TRIGGER_FILL_REQUEST_ON_UNIMPORTANT_VIEW,
373                             Boolean.toString(false)))
374 
375                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
376                             "trigger_fill_request_on_filtered_important_views",
377                             Boolean.toString(false)))
378 
379                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
380                             "include_all_autofill_type_not_none_views_in_assist_structure",
381                             Boolean.toString(false)))
382 
383 
384                 //
385                 // Max input size to provide autofill suggestion should be 3
386                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
387                             "max_input_length_for_autofill",
388                             Integer.toString(3)))
389 
390                 //
391                 // Fill fields from current session only should be on by default
392                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
393                         "fill_fields_from_current_session_only", Boolean.toString(true)))
394 
395                 //
396                 // Ignore view state reset to empty should be on by default
397                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
398                         "ignore_view_state_reset_to_empty", Boolean.toString(true)))
399 
400                 //
401                 // Include invisible view group in assist structure should be on by default
402                 .around(new DeviceConfigStateChangerRule(sContext, DeviceConfig.NAMESPACE_AUTOFILL,
403                         "include_invisible_view_group_in_assist_structure", Boolean.toString(true)))
404 
405                 //
406                 // Finally, let subclasses add their own rules (like ActivityTestRule)
407                 .around(getMainTestRule());
408 
409 
410         protected final Context mContext = sContext;
411         protected final String mPackageName;
412         protected final UiBot mUiBot;
413 
414         protected static final RuleChain sRequiredFeaturesRule = RuleChain
415                 .outerRule(new RequiredFeatureRule(PackageManager.FEATURE_AUTOFILL))
416                 .around(new RequiredFeatureRule(PackageManager.FEATURE_INPUT_METHODS));
417 
418         public BaseTestCase() {
419             mPackageName = mContext.getPackageName();
420             mUiBot = sDefaultUiBot;
421         }
422 
423         private BaseTestCase(@NonNull UiBot uiBot) {
424             mPackageName = mContext.getPackageName();
425             mUiBot = uiBot;
426             mUiBot.reset();
427         }
428 
429         protected int getSmartSuggestionMode() {
430             return AutofillManager.FLAG_SMART_SUGGESTION_OFF;
431         }
432 
433         /**
434          * Gets how many times a test should be retried.
435          *
436          * @return {@code 1} by default, unless overridden by subclasses or by a global settings
437          * named {@code CLASS_NAME + #getNumberRetries} or
438          * {@code CtsAutoFillServiceTestCases#getNumberRetries} (the former having a higher
439          * priority).
440          */
441         protected int getNumberRetries() {
442             final String localProp = getClass().getName() + "#getNumberRetries";
443             final Integer localValue = getNumberRetries(localProp);
444             if (localValue != null) return localValue.intValue();
445 
446             final String globalProp = "CtsAutoFillServiceTestCases#getNumberRetries";
447             final Integer globalValue = getNumberRetries(globalProp);
448             if (globalValue != null) return globalValue.intValue();
449 
450             return 1;
451         }
452 
453         private Integer getNumberRetries(String prop) {
454             final String value = Settings.Global.getString(sContext.getContentResolver(), prop);
455             if (value != null) {
456                 Log.i(TAG, "getNumberRetries(): overriding to " + value + " because of '" + prop
457                         + "' global setting");
458                 try {
459                     return Integer.parseInt(value);
460                 } catch (Exception e) {
461                     Log.w(TAG, "error parsing property '" + prop + "'='" + value + "'", e);
462                 }
463             }
464             return null;
465         }
466 
467         /**
468          * Gets a rule that defines which features must be present for this test to run.
469          *
470          * <p>By default it returns a rule that requires {@link PackageManager#FEATURE_AUTOFILL},
471          * but subclass can override to be more specific.
472          */
473         @NonNull
474         protected TestRule getRequiredFeaturesRule() {
475             return sRequiredFeaturesRule;
476         }
477 
478         /**
479          * Gets the test-specific {@link Rule @Rule}.
480          *
481          * <p>Sub-class <b>MUST</b> override this method instead of annotation their own rules,
482          * so the order is preserved.
483          *
484          */
485         @NonNull
486         protected abstract TestRule getMainTestRule();
487 
488         @BeforeClass
489         public static void disableDefaultAugmentedService() {
490             Log.v(TAG, "@BeforeClass: disableDefaultAugmentedService()");
491             Helper.setDefaultAugmentedAutofillServiceEnabled(false);
492         }
493 
494         @AfterClass
495         public static void enableDefaultAugmentedService() {
496             Log.v(TAG, "@AfterClass: enableDefaultAugmentedService()");
497             Helper.setDefaultAugmentedAutofillServiceEnabled(true);
498         }
499 
500         @Before
501         public void prepareDevice() throws Exception {
502             Log.v(TAG, "@Before: prepareDevice()");
503 
504             // Unlock screen.
505             runShellCommand("input keyevent KEYCODE_WAKEUP");
506 
507             // Dismiss keyguard, in case it's set as "Swipe to unlock".
508             runShellCommand("wm dismiss-keyguard");
509 
510             // Collapse notifications.
511             runShellCommand("cmd statusbar collapse");
512 
513             assumeFalse("Device is half-folded",
514                     Helper.isDeviceInState(mContext, Helper.DeviceStateEnum.HALF_FOLDED));
515 
516             assumeFalse("Device is TV", Helper.isTv(mContext));
517 
518             // Set orientation as portrait, otherwise some tests might fail due to elements not
519             // fitting in, IME orientation, etc...
520             mUiBot.maybeSetScreenOrientation(UiBot.PORTRAIT);
521 
522             // Clear Clipboard
523             // TODO(b/117768051): remove try/catch once fixed
524             try {
525                 ((ClipboardManager) mContext.getSystemService(CLIPBOARD_SERVICE))
526                     .clearPrimaryClip();
527             } catch (Exception e) {
528                 Log.e(TAG, "Ignoring exception clearing clipboard", e);
529             }
530         }
531 
532         @Before
533         public void preTestCleanup() {
534             Log.v(TAG, "@Before: preTestCleanup()");
535 
536             prepareServicePreTest();
537 
538             InstrumentedAutoFillService.resetStaticState();
539             AuthenticationActivity.resetStaticState();
540             AugmentedAuthActivity.resetStaticState();
541             sReplier.reset();
542         }
543 
544         /**
545          * Prepares the service before each test - by default, disables it
546          */
547         protected void prepareServicePreTest() {
548             Log.v(TAG, "prepareServicePreTest(): calling disableService()");
549             disableService();
550         }
551 
552         /**
553          * Enables the {@link InstrumentedAutoFillService} for autofill for the current user.
554          */
555         protected void enableService() {
556             Helper.enableAutofillService(SERVICE_NAME);
557         }
558 
559         /**
560          * Disables the {@link InstrumentedAutoFillService} for autofill for the current user.
561          */
562         protected void disableService() {
563             Helper.disableAutofillService();
564         }
565 
566         /**
567          * Asserts that the {@link InstrumentedAutoFillService} is enabled for the default user.
568          */
569         protected void assertServiceEnabled() {
570             Helper.assertAutofillServiceStatus(SERVICE_NAME, true);
571         }
572 
573         /**
574          * Asserts that the {@link InstrumentedAutoFillService} is disabled for the default user.
575          */
576         protected void assertServiceDisabled() {
577             Helper.assertAutofillServiceStatus(SERVICE_NAME, false);
578         }
579 
580         protected RemoteViews createPresentation(String message) {
581             return Helper.createPresentation(message);
582         }
583 
584         protected RemoteViews createPresentationWithCancel(String message) {
585             final RemoteViews presentation = new RemoteViews(getContext()
586                     .getPackageName(), R.layout.list_item_cancel);
587             presentation.setTextViewText(R.id.text1, message);
588             return presentation;
589         }
590 
591         protected InlinePresentation createInlinePresentation(String message) {
592             return Helper.createInlinePresentation(message);
593         }
594 
595         protected InlinePresentation createInlinePresentation(String message,
596                                                               PendingIntent attribution) {
597             return Helper.createInlinePresentation(message, attribution);
598         }
599 
600         @NonNull
601         protected AutofillManager getAutofillManager() {
602             return mContext.getSystemService(AutofillManager.class);
603         }
604 
605         /**
606          * Used to clean all activities that started by test case and does not control by the
607          * AutofillTestWatcher.
608          */
609         protected void cleanAllActivities() {}
610     }
611 
612     protected static final UiBot sDefaultUiBot = new UiBot();
613 
614     private AutoFillServiceTestCase() {
615         throw new UnsupportedOperationException("Contain static stuff only");
616     }
617 }
618