1 /* 2 * Copyright (C) 2017 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.tv.settings.accessibility; 18 19 import static android.content.Context.ACCESSIBILITY_SERVICE; 20 21 import static com.android.tv.settings.util.InstrumentationUtils.logToggleInteracted; 22 23 import android.accessibilityservice.AccessibilityServiceInfo; 24 import android.app.tvsettings.TvSettingsEnums; 25 import android.content.ComponentName; 26 import android.content.pm.ServiceInfo; 27 import android.os.Bundle; 28 import android.provider.Settings; 29 import android.text.TextUtils; 30 import android.view.accessibility.AccessibilityManager; 31 32 import androidx.annotation.Keep; 33 import androidx.preference.Preference; 34 import androidx.preference.PreferenceGroup; 35 import androidx.preference.SwitchPreference; 36 import androidx.preference.TwoStatePreference; 37 38 import com.android.internal.logging.nano.MetricsProto; 39 import com.android.settingslib.accessibility.AccessibilityUtils; 40 import com.android.tv.settings.R; 41 import com.android.tv.settings.SettingsPreferenceFragment; 42 43 import java.util.List; 44 import java.util.Set; 45 46 /** 47 * Fragment for Accessibility settings 48 */ 49 @Keep 50 public class AccessibilityFragment extends SettingsPreferenceFragment { 51 private static final String TOGGLE_HIGH_TEXT_CONTRAST_KEY = "toggle_high_text_contrast"; 52 private static final String ACCESSIBILITY_SERVICES_KEY = "system_accessibility_services"; 53 54 private PreferenceGroup mServicesPref; 55 private AccessibilityManager.AccessibilityStateChangeListener 56 mAccessibilityStateChangeListener = enabled -> refreshServices(mServicesPref); 57 58 /** 59 * Create a new instance of the fragment 60 * @return New fragment instance 61 */ newInstance()62 public static AccessibilityFragment newInstance() { 63 return new AccessibilityFragment(); 64 } 65 66 @Override onResume()67 public void onResume() { 68 super.onResume(); 69 if (mServicesPref != null) { 70 refreshServices(mServicesPref); 71 } 72 } 73 74 @Override onStop()75 public void onStop() { 76 super.onStop(); 77 AccessibilityManager am = (AccessibilityManager) 78 getContext().getSystemService(ACCESSIBILITY_SERVICE); 79 if (am != null && mServicesPref != null) { 80 am.removeAccessibilityStateChangeListener(mAccessibilityStateChangeListener); 81 } 82 } 83 84 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)85 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 86 setPreferencesFromResource(R.xml.accessibility, null); 87 88 final TwoStatePreference highContrastPreference = 89 (TwoStatePreference) findPreference(TOGGLE_HIGH_TEXT_CONTRAST_KEY); 90 highContrastPreference.setChecked(Settings.Secure.getInt(getContext().getContentResolver(), 91 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 0) == 1); 92 93 mServicesPref = (PreferenceGroup) findPreference(ACCESSIBILITY_SERVICES_KEY); 94 if (mServicesPref != null) { 95 refreshServices(mServicesPref); 96 AccessibilityManager am = (AccessibilityManager) 97 getContext().getSystemService(ACCESSIBILITY_SERVICE); 98 if (am != null) { 99 am.addAccessibilityStateChangeListener(mAccessibilityStateChangeListener); 100 } 101 } 102 } 103 104 @Override onPreferenceTreeClick(Preference preference)105 public boolean onPreferenceTreeClick(Preference preference) { 106 if (TextUtils.equals(preference.getKey(), TOGGLE_HIGH_TEXT_CONTRAST_KEY)) { 107 logToggleInteracted( 108 TvSettingsEnums.SYSTEM_A11Y_HIGH_CONTRAST_TEXT, 109 ((SwitchPreference) preference).isChecked()); 110 Settings.Secure.putInt(getActivity().getContentResolver(), 111 Settings.Secure.ACCESSIBILITY_HIGH_TEXT_CONTRAST_ENABLED, 112 (((SwitchPreference) preference).isChecked() ? 1 : 0)); 113 return true; 114 } else { 115 return super.onPreferenceTreeClick(preference); 116 } 117 } 118 refreshServices(PreferenceGroup group)119 private void refreshServices(PreferenceGroup group) { 120 final List<AccessibilityServiceInfo> installedServiceInfos = 121 getActivity().getSystemService(AccessibilityManager.class) 122 .getInstalledAccessibilityServiceList(); 123 final Set<ComponentName> enabledServices = 124 AccessibilityUtils.getEnabledServicesFromSettings(getActivity()); 125 final boolean accessibilityEnabled = Settings.Secure.getInt( 126 getActivity().getContentResolver(), 127 Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1; 128 129 for (final AccessibilityServiceInfo accInfo : installedServiceInfos) { 130 final ServiceInfo serviceInfo = accInfo.getResolveInfo().serviceInfo; 131 final ComponentName componentName = new ComponentName(serviceInfo.packageName, 132 serviceInfo.name); 133 134 final boolean serviceEnabled = accessibilityEnabled 135 && enabledServices.contains(componentName); 136 137 final String title = accInfo.getResolveInfo() 138 .loadLabel(getActivity().getPackageManager()).toString(); 139 140 final String key = "ServicePref:" + componentName.flattenToString(); 141 Preference servicePref = findPreference(key); 142 if (servicePref == null) { 143 servicePref = new Preference(group.getContext()); 144 servicePref.setKey(key); 145 } 146 servicePref.setTitle(title); 147 servicePref.setSummary(serviceEnabled ? R.string.settings_on : R.string.settings_off); 148 servicePref.setFragment(AccessibilityServiceFragment.class.getName()); 149 AccessibilityServiceFragment.prepareArgs(servicePref.getExtras(), 150 serviceInfo.packageName, 151 serviceInfo.name, 152 accInfo.getSettingsActivityName(), 153 title); 154 group.addPreference(servicePref); 155 } 156 } 157 158 @Override getMetricsCategory()159 public int getMetricsCategory() { 160 return MetricsProto.MetricsEvent.ACCESSIBILITY; 161 } 162 163 @Override getPageId()164 protected int getPageId() { 165 return TvSettingsEnums.SYSTEM_A11Y; 166 } 167 } 168