1 /*
2  * Copyright (C) 2022 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.settings.accessibility;
18 
19 import static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.Mockito.when;
23 
24 import static java.util.Collections.singletonList;
25 
26 import android.accessibilityservice.AccessibilityServiceInfo;
27 import android.accessibilityservice.AccessibilityShortcutInfo;
28 import android.content.ComponentName;
29 import android.content.Context;
30 import android.content.pm.ActivityInfo;
31 import android.content.pm.ApplicationInfo;
32 import android.content.pm.ResolveInfo;
33 import android.content.pm.ServiceInfo;
34 import android.platform.test.annotations.RequiresFlagsEnabled;
35 import android.platform.test.flag.junit.CheckFlagsRule;
36 import android.platform.test.flag.junit.DeviceFlagsValueProvider;
37 import android.platform.test.flag.junit.SetFlagsRule;
38 
39 import androidx.test.core.app.ApplicationProvider;
40 
41 import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
42 import com.android.settingslib.RestrictedPreference;
43 
44 import org.junit.Rule;
45 import org.junit.Test;
46 import org.junit.runner.RunWith;
47 import org.mockito.Mock;
48 import org.mockito.Mockito;
49 import org.mockito.Spy;
50 import org.mockito.junit.MockitoJUnit;
51 import org.mockito.junit.MockitoRule;
52 import org.robolectric.RobolectricTestRunner;
53 import org.robolectric.annotation.Config;
54 import org.xmlpull.v1.XmlPullParserException;
55 
56 import java.io.IOException;
57 import java.util.ArrayList;
58 import java.util.List;
59 
60 /** Test for {@link RestrictedPreferenceHelper}. */
61 @RunWith(RobolectricTestRunner.class)
62 @Config(shadows = {
63         ShadowRestrictedLockUtilsInternal.class
64 })
65 public class RestrictedPreferenceHelperTest {
66 
67     private static final String PACKAGE_NAME = "com.android.test";
68     private static final String CLASS_NAME = PACKAGE_NAME + ".test_a11y_service";
69     private static final ComponentName COMPONENT_NAME = new ComponentName(PACKAGE_NAME, CLASS_NAME);
70     private static final String DEFAULT_SUMMARY = "default summary";
71     private static final String DEFAULT_DESCRIPTION = "default description";
72     private static final String DEFAULT_LABEL = "default label";
73 
74     @Rule
75     public final MockitoRule mocks = MockitoJUnit.rule();
76     private final Context mContext = ApplicationProvider.getApplicationContext();
77     @Spy
78     private final AccessibilityServiceInfo mServiceInfo = getMockAccessibilityServiceInfo(
79             PACKAGE_NAME, CLASS_NAME);
80     @Mock
81     private AccessibilityShortcutInfo mShortcutInfo;
82     private final RestrictedPreferenceHelper mHelper = new RestrictedPreferenceHelper(mContext);
83 
84     @Rule
85     public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
86     @Rule
87     public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
88 
89     @Test
createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey()90     public void createAccessibilityServicePreferenceList_hasOneInfo_containsSameKey() {
91         final String key = COMPONENT_NAME.flattenToString();
92         final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
93                 singletonList(mServiceInfo));
94 
95         final List<RestrictedPreference> preferenceList =
96                 mHelper.createAccessibilityServicePreferenceList(infoList);
97         final RestrictedPreference preference = preferenceList.get(0);
98 
99         assertThat(preference.getKey()).isEqualTo(key);
100     }
101 
102     @Test
103     @RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
104             android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted()105     public void createAccessibilityServicePreferenceList_ecmRestricted_prefIsEcmRestricted() {
106         ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs(
107                 mServiceInfo.getResolveInfo().serviceInfo.packageName);
108         final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
109                 singletonList(mServiceInfo));
110 
111         final List<RestrictedPreference> preferenceList =
112                 mHelper.createAccessibilityServicePreferenceList(infoList);
113         final RestrictedPreference preference = preferenceList.get(0);
114 
115         assertThat(preference.isDisabledByEcm()).isTrue();
116     }
117 
118     @Test
119     @RequiresFlagsEnabled(value = {android.security.Flags.FLAG_EXTEND_ECM_TO_ALL_SETTINGS,
120             android.permission.flags.Flags.FLAG_ENHANCED_CONFIRMATION_MODE_APIS_ENABLED})
createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted()121     public void createAccessibilityServicePreferenceList_ecmNotRestricted_prefIsNotEcmRestricted() {
122         ShadowRestrictedLockUtilsInternal.setEcmRestrictedPkgs();
123         final List<AccessibilityServiceInfo> infoList = new ArrayList<>(
124                 singletonList(mServiceInfo));
125 
126         final List<RestrictedPreference> preferenceList =
127                 mHelper.createAccessibilityServicePreferenceList(infoList);
128         final RestrictedPreference preference = preferenceList.get(0);
129 
130         assertThat(preference.isDisabledByEcm()).isFalse();
131     }
132 
133     @Test
createAccessibilityActivityPreferenceList_hasOneInfo_containsSameKey()134     public void createAccessibilityActivityPreferenceList_hasOneInfo_containsSameKey() {
135         final String key = COMPONENT_NAME.flattenToString();
136         setMockAccessibilityShortcutInfo(mShortcutInfo);
137         final List<AccessibilityShortcutInfo> infoList = new ArrayList<>(
138                 singletonList(mShortcutInfo));
139 
140         final List<AccessibilityActivityPreference> preferenceList =
141                 mHelper.createAccessibilityActivityPreferenceList(infoList);
142         final RestrictedPreference preference = preferenceList.get(0);
143 
144         assertThat(preference.getKey()).isEqualTo(key);
145     }
146 
getMockAccessibilityServiceInfo(String packageName, String className)147     private AccessibilityServiceInfo getMockAccessibilityServiceInfo(String packageName,
148             String className) {
149         final ApplicationInfo applicationInfo = new ApplicationInfo();
150         final ServiceInfo serviceInfo = new ServiceInfo();
151         applicationInfo.packageName = packageName;
152         serviceInfo.packageName = packageName;
153         serviceInfo.name = className;
154         serviceInfo.applicationInfo = applicationInfo;
155 
156         final ResolveInfo resolveInfo = new ResolveInfo();
157         resolveInfo.serviceInfo = serviceInfo;
158         try {
159             final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
160                     mContext);
161             info.setComponentName(new ComponentName(packageName, className));
162             return info;
163         } catch (XmlPullParserException | IOException e) {
164             // Do nothing
165         }
166         return null;
167     }
168 
setMockAccessibilityShortcutInfo(AccessibilityShortcutInfo mockInfo)169     private void setMockAccessibilityShortcutInfo(AccessibilityShortcutInfo mockInfo) {
170         final ActivityInfo activityInfo = Mockito.mock(ActivityInfo.class);
171         activityInfo.applicationInfo = new ApplicationInfo();
172         when(mockInfo.getActivityInfo()).thenReturn(activityInfo);
173         when(activityInfo.loadLabel(any())).thenReturn(DEFAULT_LABEL);
174         when(mockInfo.loadSummary(any())).thenReturn(DEFAULT_SUMMARY);
175         when(mockInfo.loadDescription(any())).thenReturn(DEFAULT_DESCRIPTION);
176         when(mockInfo.getComponentName()).thenReturn(COMPONENT_NAME);
177     }
178 }
179