Home | History | Annotate | Download | only in accessibility
      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.internal.accessibility;
     18 
     19 import android.accessibilityservice.AccessibilityServiceInfo;
     20 import android.app.AlertDialog;
     21 import android.content.ComponentName;
     22 import android.content.Context;
     23 import android.content.DialogInterface;
     24 import android.content.pm.ApplicationInfo;
     25 import android.content.pm.PackageManager;
     26 import android.content.pm.ResolveInfo;
     27 import android.content.res.Resources;
     28 import android.os.Handler;
     29 import android.os.Vibrator;
     30 import android.provider.Settings;
     31 import android.support.test.runner.AndroidJUnit4;
     32 
     33 import android.test.mock.MockContentResolver;
     34 import android.text.TextUtils;
     35 import android.view.Window;
     36 import android.view.WindowManager;
     37 import android.view.accessibility.AccessibilityManager;
     38 import android.view.accessibility.IAccessibilityManager;
     39 import android.widget.Toast;
     40 import com.android.internal.R;
     41 import com.android.internal.util.test.FakeSettingsProvider;
     42 import com.android.internal.accessibility.AccessibilityShortcutController.FrameworkObjectProvider;
     43 
     44 import org.junit.After;
     45 import org.junit.Before;
     46 import org.junit.Test;
     47 import org.junit.runner.RunWith;
     48 import org.mockito.ArgumentCaptor;
     49 import org.mockito.Mock;
     50 import org.mockito.MockitoAnnotations;
     51 
     52 import java.lang.reflect.Field;
     53 import java.util.Collections;
     54 import java.util.Map;
     55 
     56 import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN;
     57 import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED;
     58 import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN;
     59 import static android.provider.Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
     60 import static junit.framework.Assert.assertEquals;
     61 import static junit.framework.Assert.assertFalse;
     62 import static junit.framework.Assert.assertTrue;
     63 
     64 import static org.junit.Assert.fail;
     65 import static org.mockito.AdditionalMatchers.aryEq;
     66 import static org.mockito.ArgumentMatchers.any;
     67 import static org.mockito.Matchers.anyBoolean;
     68 import static org.mockito.Matchers.anyInt;
     69 import static org.mockito.Matchers.anyObject;
     70 import static org.mockito.Matchers.eq;
     71 import static org.mockito.Mockito.mock;
     72 import static org.mockito.Mockito.times;
     73 import static org.mockito.Mockito.verify;
     74 import static org.mockito.Mockito.verifyZeroInteractions;
     75 import static org.mockito.Mockito.when;
     76 
     77 @RunWith(AndroidJUnit4.class)
     78 public class AccessibilityShortcutControllerTest {
     79     private static final String SERVICE_NAME_STRING = "fake.package/fake.service.name";
     80     private static final String SERVICE_NAME_SUMMARY = "Summary";
     81     private static final long VIBRATOR_PATTERN_1 = 100L;
     82     private static final long VIBRATOR_PATTERN_2 = 150L;
     83     private static final int[] VIBRATOR_PATTERN_INT = {(int) VIBRATOR_PATTERN_1,
     84             (int) VIBRATOR_PATTERN_2};
     85     private static final long[] VIBRATOR_PATTERN_LONG = {VIBRATOR_PATTERN_1, VIBRATOR_PATTERN_2};
     86 
     87     // Convenience values for enabling/disabling to make code more readable
     88     private static final int DISABLED = 0;
     89     private static final int ENABLED_EXCEPT_LOCK_SCREEN = 1;
     90     private static final int ENABLED_INCLUDING_LOCK_SCREEN = 2;
     91     private static final int DISABLED_BUT_LOCK_SCREEN_ON = 3;
     92 
     93     private @Mock Context mContext;
     94     private @Mock FrameworkObjectProvider mFrameworkObjectProvider;
     95     private @Mock IAccessibilityManager mAccessibilityManagerService;
     96     private @Mock Handler mHandler;
     97     private @Mock AlertDialog.Builder mAlertDialogBuilder;
     98     private @Mock AlertDialog mAlertDialog;
     99     private @Mock AccessibilityServiceInfo mServiceInfo;
    100     private @Mock Resources mResources;
    101     private @Mock Toast mToast;
    102     private @Mock Vibrator mVibrator;
    103     private @Mock ApplicationInfo mApplicationInfo;
    104     private @Mock PackageManager mPackageManager;
    105 
    106     private MockContentResolver mContentResolver;
    107     private WindowManager.LayoutParams mLayoutParams = new WindowManager.LayoutParams();
    108 
    109     @Before
    110     public void setUp() throws Exception {
    111         MockitoAnnotations.initMocks(this);
    112 
    113         when(mVibrator.hasVibrator()).thenReturn(true);
    114 
    115         when(mContext.getResources()).thenReturn(mResources);
    116         when(mContext.getApplicationInfo()).thenReturn(mApplicationInfo);
    117         when(mContext.getSystemService(Context.VIBRATOR_SERVICE)).thenReturn(mVibrator);
    118         when(mContext.getPackageManager()).thenReturn(mPackageManager);
    119 
    120         // We're not checking the text. Just prevent us crashing when getting text.
    121         when(mPackageManager.getText(any(), anyInt(), any())).thenReturn("text");
    122 
    123         mContentResolver = new MockContentResolver(mContext);
    124         mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
    125         when(mContext.getContentResolver()).thenReturn(mContentResolver);
    126 
    127         when(mAccessibilityManagerService.getInstalledAccessibilityServiceList(anyInt()))
    128                 .thenReturn(Collections.singletonList(mServiceInfo));
    129 
    130         // Use the extra level of indirection in the object to mock framework objects
    131         AccessibilityManager accessibilityManager =
    132                 new AccessibilityManager(mHandler, mAccessibilityManagerService, 0);
    133         when(mFrameworkObjectProvider.getAccessibilityManagerInstance(mContext))
    134                 .thenReturn(accessibilityManager);
    135         when(mFrameworkObjectProvider.getAlertDialogBuilder(mContext))
    136                 .thenReturn(mAlertDialogBuilder);
    137         when(mFrameworkObjectProvider.makeToastFromText(eq(mContext), anyObject(), anyInt()))
    138                 .thenReturn(mToast);
    139         when(mFrameworkObjectProvider.getSystemUiContext()).thenReturn(mContext);
    140 
    141         when(mResources.getString(anyInt())).thenReturn("Howdy %s");
    142         when(mResources.getIntArray(anyInt())).thenReturn(VIBRATOR_PATTERN_INT);
    143 
    144         ResolveInfo resolveInfo = mock(ResolveInfo.class);
    145         when(resolveInfo.loadLabel(anyObject())).thenReturn("Service name");
    146         when(mServiceInfo.getResolveInfo()).thenReturn(resolveInfo);
    147         when(mServiceInfo.getComponentName())
    148                 .thenReturn(ComponentName.unflattenFromString(SERVICE_NAME_STRING));
    149         when(mServiceInfo.loadSummary(any())).thenReturn(SERVICE_NAME_SUMMARY);
    150 
    151         when(mAlertDialogBuilder.setTitle(anyInt())).thenReturn(mAlertDialogBuilder);
    152         when(mAlertDialogBuilder.setCancelable(anyBoolean())).thenReturn(mAlertDialogBuilder);
    153         when(mAlertDialogBuilder.setMessage(anyObject())).thenReturn(mAlertDialogBuilder);
    154         when(mAlertDialogBuilder.setPositiveButton(anyInt(), anyObject()))
    155                 .thenReturn(mAlertDialogBuilder);
    156         when(mAlertDialogBuilder.setNegativeButton(anyInt(), anyObject()))
    157                 .thenReturn(mAlertDialogBuilder);
    158         when(mAlertDialogBuilder.setOnCancelListener(anyObject())).thenReturn(mAlertDialogBuilder);
    159         when(mAlertDialogBuilder.create()).thenReturn(mAlertDialog);
    160 
    161         mLayoutParams.privateFlags = 0;
    162         when(mToast.getWindowParams()).thenReturn(mLayoutParams);
    163 
    164         Window window = mock(Window.class);
    165         // Initialize the mWindowAttributes field which was not properly initialized during mock
    166         // creation.
    167         try {
    168             Field field = Window.class.getDeclaredField("mWindowAttributes");
    169             field.setAccessible(true);
    170             field.set(window, new WindowManager.LayoutParams());
    171         } catch (Exception e) {
    172             throw new RuntimeException("Unable to set mWindowAttributes", e);
    173         }
    174         when(mAlertDialog.getWindow()).thenReturn(window);
    175     }
    176 
    177     @After
    178     public void tearDown() {
    179     }
    180 
    181     @Test
    182     public void testShortcutAvailable_enabledButNoServiceWhenCreated_shouldReturnFalse() {
    183         configureNoShortcutService();
    184         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    185         assertFalse(getController().isAccessibilityShortcutAvailable(false));
    186     }
    187 
    188     @Test
    189     public void testShortcutAvailable_enabledWithValidServiceWhenCreated_shouldReturnTrue() {
    190         configureValidShortcutService();
    191         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    192         assertTrue(getController().isAccessibilityShortcutAvailable(false));
    193     }
    194 
    195     @Test
    196     public void testShortcutAvailable_disabledWithValidServiceWhenCreated_shouldReturnFalse() {
    197         configureValidShortcutService();
    198         configureShortcutEnabled(DISABLED_BUT_LOCK_SCREEN_ON);
    199         assertFalse(getController().isAccessibilityShortcutAvailable(false));
    200     }
    201 
    202     @Test
    203     public void testShortcutAvailable_onLockScreenButDisabledThere_shouldReturnFalse() {
    204         configureValidShortcutService();
    205         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    206         assertFalse(getController().isAccessibilityShortcutAvailable(true));
    207     }
    208 
    209     @Test
    210     public void testShortcutAvailable_onLockScreenAndEnabledThere_shouldReturnTrue() {
    211         configureValidShortcutService();
    212         configureShortcutEnabled(ENABLED_INCLUDING_LOCK_SCREEN);
    213         assertTrue(getController().isAccessibilityShortcutAvailable(true));
    214     }
    215 
    216     @Test
    217     public void testShortcutAvailable_onLockScreenAndLockScreenPreferenceUnset() {
    218         // When the user hasn't specified a lock screen preference, we allow from the lock screen
    219         // as long as the user has agreed to enable the shortcut
    220         configureValidShortcutService();
    221         configureShortcutEnabled(ENABLED_INCLUDING_LOCK_SCREEN);
    222         Settings.Secure.putString(
    223                 mContentResolver, ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, null);
    224         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
    225         assertFalse(getController().isAccessibilityShortcutAvailable(true));
    226         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 1);
    227         assertTrue(getController().isAccessibilityShortcutAvailable(true));
    228     }
    229 
    230     @Test
    231     public void testShortcutAvailable_whenServiceIdBecomesNull_shouldReturnFalse() {
    232         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    233         configureValidShortcutService();
    234         AccessibilityShortcutController accessibilityShortcutController = getController();
    235         Settings.Secure.putString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "");
    236         accessibilityShortcutController.onSettingsChanged();
    237         assertFalse(accessibilityShortcutController.isAccessibilityShortcutAvailable(false));
    238     }
    239 
    240     @Test
    241     public void testShortcutAvailable_whenServiceIdBecomesNonNull_shouldReturnTrue() {
    242         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    243         configureNoShortcutService();
    244         AccessibilityShortcutController accessibilityShortcutController = getController();
    245         configureValidShortcutService();
    246         accessibilityShortcutController.onSettingsChanged();
    247         assertTrue(accessibilityShortcutController.isAccessibilityShortcutAvailable(false));
    248     }
    249 
    250     @Test
    251     public void testShortcutAvailable_whenShortcutBecomesDisabled_shouldReturnFalse() {
    252         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    253         configureValidShortcutService();
    254         AccessibilityShortcutController accessibilityShortcutController = getController();
    255         configureShortcutEnabled(DISABLED);
    256         accessibilityShortcutController.onSettingsChanged();
    257         assertFalse(accessibilityShortcutController.isAccessibilityShortcutAvailable(false));
    258     }
    259 
    260     @Test
    261     public void testShortcutAvailable_whenShortcutBecomesEnabled_shouldReturnTrue() {
    262         configureShortcutEnabled(DISABLED);
    263         configureValidShortcutService();
    264         AccessibilityShortcutController accessibilityShortcutController = getController();
    265         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    266         accessibilityShortcutController.onSettingsChanged();
    267         assertTrue(accessibilityShortcutController.isAccessibilityShortcutAvailable(false));
    268     }
    269 
    270     @Test
    271     public void testShortcutAvailable_whenLockscreenBecomesDisabled_shouldReturnFalse() {
    272         configureShortcutEnabled(ENABLED_INCLUDING_LOCK_SCREEN);
    273         configureValidShortcutService();
    274         AccessibilityShortcutController accessibilityShortcutController = getController();
    275         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    276         accessibilityShortcutController.onSettingsChanged();
    277         assertFalse(accessibilityShortcutController.isAccessibilityShortcutAvailable(true));
    278     }
    279 
    280     @Test
    281     public void testShortcutAvailable_whenLockscreenBecomesEnabled_shouldReturnTrue() {
    282         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    283         configureValidShortcutService();
    284         AccessibilityShortcutController accessibilityShortcutController = getController();
    285         configureShortcutEnabled(ENABLED_INCLUDING_LOCK_SCREEN);
    286         accessibilityShortcutController.onSettingsChanged();
    287         assertTrue(accessibilityShortcutController.isAccessibilityShortcutAvailable(true));
    288     }
    289 
    290     @Test
    291     public void testOnAccessibilityShortcut_vibrates() {
    292         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    293         AccessibilityShortcutController accessibilityShortcutController = getController();
    294         accessibilityShortcutController.performAccessibilityShortcut();
    295         verify(mVibrator).vibrate(aryEq(VIBRATOR_PATTERN_LONG), eq(-1), anyObject());
    296     }
    297 
    298     @Test
    299     public void testOnAccessibilityShortcut_firstTime_showsWarningDialog()
    300             throws Exception {
    301         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    302         configureValidShortcutService();
    303         AccessibilityShortcutController accessibilityShortcutController = getController();
    304         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
    305         accessibilityShortcutController.performAccessibilityShortcut();
    306 
    307         assertEquals(1, Settings.Secure.getInt(
    308                 mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0));
    309         verify(mResources).getString(R.string.accessibility_shortcut_toogle_warning);
    310         verify(mAlertDialog).show();
    311         verify(mAccessibilityManagerService).getInstalledAccessibilityServiceList(anyInt());
    312         verify(mAccessibilityManagerService, times(0)).performAccessibilityShortcut();
    313     }
    314 
    315     @Test
    316     public void testOnAccessibilityShortcut_withDialogShowing_callsServer()
    317         throws Exception {
    318         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    319         configureValidShortcutService();
    320         AccessibilityShortcutController accessibilityShortcutController = getController();
    321         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
    322         accessibilityShortcutController.performAccessibilityShortcut();
    323         accessibilityShortcutController.performAccessibilityShortcut();
    324         verify(mToast).show();
    325         assertEquals(WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS,
    326                 mLayoutParams.privateFlags
    327                         & WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS);
    328         verify(mAccessibilityManagerService, times(1)).performAccessibilityShortcut();
    329     }
    330 
    331     @Test
    332     public void testOnAccessibilityShortcut_ifCanceledFirstTime_showsWarningDialog()
    333         throws Exception {
    334         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    335         configureValidShortcutService();
    336         AccessibilityShortcutController accessibilityShortcutController = getController();
    337         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
    338         accessibilityShortcutController.performAccessibilityShortcut();
    339         ArgumentCaptor<AlertDialog.OnCancelListener> cancelListenerCaptor =
    340                 ArgumentCaptor.forClass(AlertDialog.OnCancelListener.class);
    341         verify(mAlertDialogBuilder).setOnCancelListener(cancelListenerCaptor.capture());
    342         // Call the cancel callback
    343         cancelListenerCaptor.getValue().onCancel(null);
    344 
    345         accessibilityShortcutController.performAccessibilityShortcut();
    346         verify(mAlertDialog, times(2)).show();
    347     }
    348 
    349     @Test
    350     public void testClickingDisableButtonInDialog_shouldClearShortcutId() {
    351         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    352         configureValidShortcutService();
    353         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
    354         getController().performAccessibilityShortcut();
    355 
    356         ArgumentCaptor<DialogInterface.OnClickListener> captor =
    357                 ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
    358         verify(mAlertDialogBuilder).setNegativeButton(eq(R.string.disable_accessibility_shortcut),
    359                 captor.capture());
    360         // Call the button callback
    361         captor.getValue().onClick(null, 0);
    362         assertTrue(TextUtils.isEmpty(
    363                 Settings.Secure.getString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE)));
    364     }
    365 
    366     @Test
    367     public void testClickingLeaveOnButtonInDialog_shouldLeaveShortcutReady() throws Exception {
    368         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    369         configureValidShortcutService();
    370         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 0);
    371         getController().performAccessibilityShortcut();
    372 
    373         ArgumentCaptor<DialogInterface.OnClickListener> captor =
    374             ArgumentCaptor.forClass(DialogInterface.OnClickListener.class);
    375         verify(mAlertDialogBuilder).setPositiveButton(eq(R.string.leave_accessibility_shortcut_on),
    376             captor.capture());
    377         // Call the button callback, if one exists
    378         if (captor.getValue() != null) {
    379             captor.getValue().onClick(null, 0);
    380         }
    381         assertEquals(SERVICE_NAME_STRING,
    382                 Settings.Secure.getString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE));
    383         assertEquals(1, Settings.Secure.getInt(
    384             mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN));
    385     }
    386 
    387     @Test
    388     public void testOnAccessibilityShortcut_afterDialogShown_shouldCallServer() throws Exception {
    389         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    390         configureValidShortcutService();
    391         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 1);
    392         getController().performAccessibilityShortcut();
    393 
    394         verifyZeroInteractions(mAlertDialogBuilder, mAlertDialog);
    395         verify(mToast).show();
    396         verify(mAccessibilityManagerService).performAccessibilityShortcut();
    397     }
    398 
    399     @Test
    400     public void getFrameworkFeatureMap_shouldBeNonNullAndUnmodifiable() {
    401         Map<ComponentName, AccessibilityShortcutController.ToggleableFrameworkFeatureInfo>
    402                 frameworkFeatureMap =
    403                 AccessibilityShortcutController.getFrameworkShortcutFeaturesMap();
    404         assertTrue("Framework features not supported", frameworkFeatureMap.size() > 0);
    405 
    406         try {
    407             frameworkFeatureMap.clear();
    408             fail("Framework feature map should be unmodifieable");
    409         } catch (UnsupportedOperationException e) {
    410             // Expected
    411         }
    412     }
    413 
    414     @Test
    415     public void testOnAccessibilityShortcut_forServiceWithNoSummary_doesNotCrash()
    416             throws Exception {
    417         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    418         configureValidShortcutService();
    419         when(mServiceInfo.loadSummary(any())).thenReturn(null);
    420         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 1);
    421         getController().performAccessibilityShortcut();
    422         verify(mAccessibilityManagerService).performAccessibilityShortcut();
    423     }
    424 
    425     @Test
    426     public void testOnAccessibilityShortcut_forFrameworkFeature_callsServiceWithNoToast()
    427             throws Exception {
    428         configureShortcutEnabled(ENABLED_EXCEPT_LOCK_SCREEN);
    429         configureFirstFrameworkFeature();
    430         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_DIALOG_SHOWN, 1);
    431         getController().performAccessibilityShortcut();
    432 
    433         verifyZeroInteractions(mToast);
    434         verify(mAccessibilityManagerService).performAccessibilityShortcut();
    435     }
    436 
    437     private void configureNoShortcutService() {
    438         Settings.Secure.putString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, "");
    439     }
    440 
    441     private void configureValidShortcutService() {
    442         Settings.Secure.putString(
    443                 mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, SERVICE_NAME_STRING);
    444     }
    445 
    446     private void configureFirstFrameworkFeature() {
    447         ComponentName featureComponentName =
    448                 (ComponentName) AccessibilityShortcutController.getFrameworkShortcutFeaturesMap()
    449                         .keySet().toArray()[0];
    450         Settings.Secure.putString(mContentResolver, ACCESSIBILITY_SHORTCUT_TARGET_SERVICE,
    451                 featureComponentName.flattenToString());
    452     }
    453 
    454     private void configureShortcutEnabled(int enabledValue) {
    455         final boolean enabled;
    456         final boolean lockscreen;
    457 
    458         switch (enabledValue) {
    459             case DISABLED:
    460                 enabled = false;
    461                 lockscreen = false;
    462                 break;
    463             case DISABLED_BUT_LOCK_SCREEN_ON:
    464                 enabled = false;
    465                 lockscreen = true;
    466                 break;
    467             case ENABLED_INCLUDING_LOCK_SCREEN:
    468                 enabled = true;
    469                 lockscreen = true;
    470                 break;
    471             case ENABLED_EXCEPT_LOCK_SCREEN:
    472                 enabled = true;
    473                 lockscreen = false;
    474                 break;
    475             default:
    476                 throw new IllegalArgumentException();
    477         }
    478 
    479         Settings.Secure.putInt(mContentResolver, ACCESSIBILITY_SHORTCUT_ENABLED, enabled ? 1 : 0);
    480         Settings.Secure.putInt(
    481                 mContentResolver, ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, lockscreen ? 1 : 0);
    482     }
    483 
    484     private AccessibilityShortcutController getController() {
    485         AccessibilityShortcutController accessibilityShortcutController =
    486                 new AccessibilityShortcutController(mContext, mHandler, 0);
    487         accessibilityShortcutController.mFrameworkObjectProvider = mFrameworkObjectProvider;
    488         return accessibilityShortcutController;
    489     }
    490 }
    491