• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.view.textclassifier;
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.content.ComponentName;
26 import android.content.Context;
27 import android.content.ContextWrapper;
28 import android.content.Intent;
29 import android.content.pm.ActivityInfo;
30 import android.content.pm.ApplicationInfo;
31 import android.content.pm.PackageManager;
32 import android.content.pm.ResolveInfo;
33 
34 import androidx.test.InstrumentationRegistry;
35 
36 import com.google.common.base.Preconditions;
37 
38 import org.mockito.stubbing.Answer;
39 
40 import java.util.HashMap;
41 import java.util.Map;
42 import java.util.UUID;
43 
44 /**
45  * A builder used to build a fake context for testing.
46  */
47 public final class FakeContextBuilder {
48 
49     /**
50      * A component name that can be used for tests.
51      */
52     public static final ComponentName DEFAULT_COMPONENT = new ComponentName("pkg", "cls");
53 
54     private final PackageManager mPackageManager;
55     private final ContextWrapper mContext;
56     private final Map<String, ComponentName> mComponents = new HashMap<>();
57     private final Map<String, CharSequence> mAppLabels = new HashMap<>();
58     private @Nullable ComponentName mAllIntentComponent;
59 
FakeContextBuilder()60     public FakeContextBuilder() {
61         mPackageManager = mock(PackageManager.class);
62         when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(null);
63         mContext = new ContextWrapper(InstrumentationRegistry.getTargetContext()) {
64             @Override
65             public PackageManager getPackageManager() {
66                 return mPackageManager;
67             }
68         };
69     }
70 
71     /**
72      * Sets the component name of an activity to handle the specified intent action.
73      * <p>
74      * <strong>NOTE: </strong>By default, no component is set to handle any intent.
75      */
setIntentComponent( String intentAction, @Nullable ComponentName component)76     public FakeContextBuilder setIntentComponent(
77             String intentAction, @Nullable ComponentName component) {
78         Preconditions.checkNotNull(intentAction);
79         mComponents.put(intentAction, component);
80         return this;
81     }
82 
83     /**
84      * Sets the app label res for a specified package.
85      */
setAppLabel(String packageName, @Nullable CharSequence appLabel)86     public FakeContextBuilder setAppLabel(String packageName, @Nullable CharSequence appLabel) {
87         Preconditions.checkNotNull(packageName);
88         mAppLabels.put(packageName, appLabel);
89         return this;
90     }
91 
92     /**
93      * Sets the component name of an activity to handle all intents.
94      * <p>
95      * <strong>NOTE: </strong>By default, no component is set to handle any intent.
96      */
setAllIntentComponent(@ullable ComponentName component)97     public FakeContextBuilder setAllIntentComponent(@Nullable ComponentName component) {
98         mAllIntentComponent = component;
99         return this;
100     }
101 
102     /**
103      * Builds and returns a fake context.
104      */
build()105     public Context build() {
106         when(mPackageManager.resolveActivity(any(Intent.class), anyInt())).thenAnswer(
107                 (Answer<ResolveInfo>) invocation -> {
108                     final String action = ((Intent) invocation.getArgument(0)).getAction();
109                     final ComponentName component = mComponents.containsKey(action)
110                             ? mComponents.get(action)
111                             : mAllIntentComponent;
112                     return getResolveInfo(component);
113                 });
114         when(mPackageManager.getApplicationLabel(any(ApplicationInfo.class))).thenAnswer(
115                 (Answer<CharSequence>) invocation -> {
116                     ApplicationInfo applicationInfo = invocation.getArgument(0);
117                     return mAppLabels.get(applicationInfo.packageName);
118                 });
119         return mContext;
120     }
121 
122     /**
123      * Returns a component name with random package and class names.
124      */
newComponent()125     public static ComponentName newComponent() {
126         return new ComponentName(UUID.randomUUID().toString(), UUID.randomUUID().toString());
127     }
128 
getResolveInfo(ComponentName component)129     private static ResolveInfo getResolveInfo(ComponentName component) {
130         final ResolveInfo info;
131         if (component == null) {
132             info = null;
133         } else {
134             // NOTE: If something breaks in TextClassifier because we expect more fields to be set
135             // in here, just add them.
136             info = new ResolveInfo();
137             info.activityInfo = new ActivityInfo();
138             info.activityInfo.packageName = component.getPackageName();
139             info.activityInfo.name = component.getClassName();
140             info.activityInfo.exported = true;
141             info.activityInfo.applicationInfo = new ApplicationInfo();
142             info.activityInfo.applicationInfo.packageName = component.getPackageName();
143             info.activityInfo.applicationInfo.icon = 0;
144         }
145         return info;
146     }
147 
148 }
149