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 com.android.settings.accessibility;
18 
19 import static com.android.settings.core.BasePreferenceController.AVAILABLE;
20 import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
21 
22 import static com.google.common.truth.Truth.assertThat;
23 
24 import android.accessibilityservice.AccessibilityServiceInfo;
25 import android.content.ComponentName;
26 import android.content.ContentResolver;
27 import android.content.Context;
28 import android.content.pm.ResolveInfo;
29 import android.content.pm.ServiceInfo;
30 import android.provider.Settings;
31 import android.view.accessibility.AccessibilityManager;
32 
33 import com.android.settingslib.accessibility.AccessibilityUtils;
34 
35 import org.junit.Before;
36 import org.junit.Test;
37 import org.junit.runner.RunWith;
38 import org.robolectric.RobolectricTestRunner;
39 import org.robolectric.RuntimeEnvironment;
40 import org.robolectric.shadow.api.Shadow;
41 import org.robolectric.shadows.ShadowAccessibilityManager;
42 import org.xmlpull.v1.XmlPullParserException;
43 
44 import java.io.IOException;
45 import java.util.ArrayList;
46 import java.util.List;
47 
48 @RunWith(RobolectricTestRunner.class)
49 public class AccessibilitySlicePreferenceControllerTest {
50 
51     private final String PACKAGE_NAME = "com.android.settings.fake";
52     private final String CLASS_NAME = "com.android.settings.fake.classname";
53     private final String SERVICE_NAME = PACKAGE_NAME + "/" + CLASS_NAME;
54 
55     private Context mContext;
56 
57     private AccessibilitySlicePreferenceController mController;
58 
59     @Before
setUp()60     public void setUp() {
61         mContext = RuntimeEnvironment.application;
62 
63         final ContentResolver contentResolver = mContext.getContentResolver();
64         Settings.Secure.putInt(contentResolver, Settings.Secure.ACCESSIBILITY_ENABLED, 1 /* on */);
65         Settings.Secure.putString(contentResolver, Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
66                 SERVICE_NAME);
67 
68         // Register the fake a11y Service
69         ShadowAccessibilityManager shadowAccessibilityManager = Shadow.extract(
70                 RuntimeEnvironment.application.getSystemService(AccessibilityManager.class));
71         shadowAccessibilityManager.setInstalledAccessibilityServiceList(getFakeServiceList());
72 
73         mController = new AccessibilitySlicePreferenceController(mContext, SERVICE_NAME);
74     }
75 
76     @Test
getAvailability_availableService_returnsAvailable()77     public void getAvailability_availableService_returnsAvailable() {
78         assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
79     }
80 
81     @Test
getAvailability_unknownService_returnsUnsupported()82     public void getAvailability_unknownService_returnsUnsupported() {
83         AccessibilitySlicePreferenceController controller =
84                 new AccessibilitySlicePreferenceController(mContext, "fake_service/name");
85 
86         assertThat(controller.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
87     }
88 
89     @Test
setChecked_availableService_serviceIsEnabled()90     public void setChecked_availableService_serviceIsEnabled() {
91         mController.setChecked(true);
92 
93         assertThat(mController.isChecked()).isTrue();
94     }
95 
96     @Test
setNotChecked_availableService_serviceIsDisabled()97     public void setNotChecked_availableService_serviceIsDisabled() {
98         mController.setChecked(false);
99 
100         assertThat(mController.isChecked()).isFalse();
101     }
102 
103     @Test
isChecked_serviceEnabled_returnsTrue()104     public void isChecked_serviceEnabled_returnsTrue() {
105         AccessibilityUtils.setAccessibilityServiceState(mContext,
106                 ComponentName.unflattenFromString(mController.getPreferenceKey()), true);
107 
108         assertThat(mController.isChecked()).isTrue();
109     }
110 
111     @Test
isChecked_serviceNotEnabled_returnsFalse()112     public void isChecked_serviceNotEnabled_returnsFalse() {
113         AccessibilitySlicePreferenceController controller =
114                 new AccessibilitySlicePreferenceController(mContext, "fake_service/name");
115 
116         assertThat(controller.isChecked()).isFalse();
117     }
118 
119     @Test(expected = IllegalArgumentException.class)
illegalServiceName_exceptionThrown()120     public void illegalServiceName_exceptionThrown() {
121         new AccessibilitySlicePreferenceController(mContext, "not_split_by_slash");
122     }
123 
124     @Test
isSliceable_returnTrue()125     public void isSliceable_returnTrue() {
126         assertThat(mController.isSliceable()).isTrue();
127     }
128 
129     @Test
isPublicSlice_returnTrue()130     public void isPublicSlice_returnTrue() {
131         assertThat(mController.isPublicSlice()).isTrue();
132     }
133 
getFakeServiceList()134     private List<AccessibilityServiceInfo> getFakeServiceList() {
135         final List<AccessibilityServiceInfo> infoList = new ArrayList<>();
136 
137         final ServiceInfo serviceInfo = new ServiceInfo();
138         serviceInfo.packageName = PACKAGE_NAME;
139         serviceInfo.name = CLASS_NAME;
140 
141         final ResolveInfo resolveInfo = new ResolveInfo();
142         resolveInfo.serviceInfo = serviceInfo;
143 
144         try {
145             final AccessibilityServiceInfo info = new AccessibilityServiceInfo(resolveInfo,
146                     mContext);
147             ComponentName componentName = new ComponentName(PACKAGE_NAME, CLASS_NAME);
148             info.setComponentName(componentName);
149             infoList.add(info);
150         } catch (XmlPullParserException | IOException e) {
151 
152         }
153 
154         return infoList;
155     }
156 }
157