1296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver/* 2296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * Copyright (C) 2017 The Android Open Source Project 3296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * 4296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * Licensed under the Apache License, Version 2.0 (the "License"); 5296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * you may not use this file except in compliance with the License. 6296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * You may obtain a copy of the License at 7296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * 8296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * http://www.apache.org/licenses/LICENSE-2.0 9296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * 10296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * Unless required by applicable law or agreed to in writing, software 11296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * distributed under the License is distributed on an "AS IS" BASIS, 12296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * See the License for the specific language governing permissions and 14296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * limitations under the License. 15296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver */ 16296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverpackage com.android.settings.accessibility; 17296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 18296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.accessibilityservice.AccessibilityServiceInfo; 19296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.content.ComponentName; 20296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.content.ContentResolver; 21296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.content.Context; 22296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.os.Bundle; 23296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.os.UserHandle; 24296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.provider.Settings; 25296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.support.v14.preference.SwitchPreference; 26296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.support.v7.preference.Preference; 27296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.text.TextUtils; 28296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.view.accessibility.AccessibilityManager; 29296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.widget.Switch; 30296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 31296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.internal.logging.nano.MetricsProto.MetricsEvent; 32296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settings.R; 33296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settings.search.BaseSearchIndexProvider; 34296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settings.search.Indexable; 35296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settingslib.accessibility.AccessibilityUtils; 36296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 37296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver/** 38296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * Settings page for accessibility shortcut 39296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver */ 40296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverpublic class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePreferenceFragment 41296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver implements Indexable { 42296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 43296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public static final String SHORTCUT_SERVICE_KEY = "accessibility_shortcut_service"; 44296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public static final String ON_LOCK_SCREEN_KEY = "accessibility_shortcut_on_lock_screen"; 45296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 46296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver private Preference mServicePreference; 47296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver private SwitchPreference mOnLockScreenSwitchPreference; 48296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 49296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 50296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public int getMetricsCategory() { 51296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE; 52296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 53296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 54296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 55179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang protected int getHelpResource() { 56179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang return R.string.help_url_accessibility_shortcut; 57179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang } 58179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang 59179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang @Override 60296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public void onCreate(Bundle savedInstanceState) { 61296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver super.onCreate(savedInstanceState); 62296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 63296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver addPreferencesFromResource(R.xml.accessibility_shortcut_settings); 64296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver mServicePreference = findPreference(SHORTCUT_SERVICE_KEY); 65296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver mOnLockScreenSwitchPreference = (SwitchPreference) findPreference(ON_LOCK_SCREEN_KEY); 66296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver mOnLockScreenSwitchPreference.setOnPreferenceChangeListener((Preference p, Object o) -> { 67296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver Settings.Secure.putInt(getContentResolver(), 68296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, 69296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver ((Boolean) o) ? 1 : 0); 70296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return true; 71296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver }); 72296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver mFooterPreferenceMixin.createFooterPreference() 73296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver .setTitle(R.string.accessibility_shortcut_description); 74296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 75296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 76296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 77296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public void onResume() { 78296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver super.onResume(); 79296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver updatePreferences(); 80296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 81296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 82296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 83296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver protected void onInstallSwitchBarToggleSwitch() { 84296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver super.onInstallSwitchBarToggleSwitch(); 85296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver mSwitchBar.addOnSwitchChangeListener((Switch switchView, boolean enabled) -> { 868fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver Context context = getContext(); 878fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver if (enabled && (getServiceInfo(context) == null)) { 888fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver // If no service is configured, we'll disable the shortcut shortly. Give the 898fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver // user a chance to select a service. We'll update the preferences when we resume. 908fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver Settings.Secure.putInt( 918fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1); 928fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver mServicePreference.setEnabled(true); 938fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver mServicePreference.performClick(); 948fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver } else { 958fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver onPreferenceToggled(Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, enabled); 968fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver } 97296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver }); 98296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 99296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 100296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 101296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver protected void onPreferenceToggled(String preferenceKey, boolean enabled) { 102296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver Settings.Secure.putInt(getContentResolver(), preferenceKey, enabled ? 1 : 0); 1038fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver updatePreferences(); 104296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 105296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 106296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver private void updatePreferences() { 107296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver ContentResolver cr = getContentResolver(); 1088fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver Context context = getContext(); 1098fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver mServicePreference.setSummary(getServiceName(context)); 1108fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver if (getServiceInfo(context) == null) { 1118fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver // If no service is configured, make sure the overall shortcut is turned off 1128fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver Settings.Secure.putInt( 1138fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0); 1148fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver } 115296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver boolean isEnabled = Settings.Secure 116296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver .getInt(cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1) == 1; 1178fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver mSwitchBar.setChecked(isEnabled); 118296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver mOnLockScreenSwitchPreference.setChecked(Settings.Secure.getInt( 119a989b19646bbeaebb233aa746a816fb97996e23bPhil Weaver cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, 0) == 1); 1208fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver // Only enable changing the service and lock screen behavior if the shortcut is on 1218fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver mServicePreference.setEnabled(mToggleSwitch.isChecked()); 1228fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver mOnLockScreenSwitchPreference.setEnabled(mToggleSwitch.isChecked()); 123296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 124296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 125296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver /** 126296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * Get the user-visible name of the service currently selected for the shortcut. 127296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * 128296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * @param context The current context 129296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * @return The name of the service or a string saying that none is selected. 130296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver */ 131296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public static CharSequence getServiceName(Context context) { 1328fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver AccessibilityServiceInfo shortcutServiceInfo = getServiceInfo(context); 133296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver if (shortcutServiceInfo != null) { 134296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return shortcutServiceInfo.getResolveInfo().loadLabel(context.getPackageManager()); 135296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 136296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return context.getString(R.string.accessibility_no_service_selected); 137296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 138296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 1398fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver private static AccessibilityServiceInfo getServiceInfo(Context context) { 1408fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver ComponentName shortcutServiceName = ComponentName.unflattenFromString( 1418fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver AccessibilityUtils.getShortcutTargetServiceComponentNameString( 1428fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver context, UserHandle.myUserId())); 1438fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver return AccessibilityManager.getInstance(context) 1448fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver .getInstalledServiceInfoWithComponentName(shortcutServiceName); 1458fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver } 1468fcf4d83493eef3a76bbf729277fdc08a383c9adPhil Weaver 147296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = 148296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver new BaseSearchIndexProvider() { 149296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver // This fragment is for details of the shortcut. Only the shortcut itself needs 150296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver // to be indexed. 151296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver protected boolean isPageSearchEnabled(Context context) { 152296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return false; 153296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 154296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver }; 155296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver} 156