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 android.app.tvsettings.TvSettingsEnums; 20 import android.content.ComponentName; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.Bundle; 24 import android.text.TextUtils; 25 26 import androidx.annotation.NonNull; 27 import androidx.preference.Preference; 28 import androidx.preference.PreferenceScreen; 29 import androidx.preference.SwitchPreference; 30 import androidx.preference.TwoStatePreference; 31 32 import com.android.internal.logging.nano.MetricsProto; 33 import com.android.settingslib.accessibility.AccessibilityUtils; 34 import com.android.tv.settings.R; 35 import com.android.tv.settings.SettingsPreferenceFragment; 36 37 import java.util.Set; 38 39 /** 40 * Fragment for controlling accessibility service 41 */ 42 public class AccessibilityServiceFragment extends SettingsPreferenceFragment implements 43 AccessibilityServiceConfirmationFragment.OnAccessibilityServiceConfirmedListener { 44 private static final String ARG_PACKAGE_NAME = "packageName"; 45 private static final String ARG_SERVICE_NAME = "serviceName"; 46 private static final String ARG_SETTINGS_ACTIVITY_NAME = "settingsActivityName"; 47 private static final String ARG_LABEL = "label"; 48 49 private TwoStatePreference mEnablePref; 50 51 /** 52 * Put args in bundle 53 * @param args Bundle to prepare 54 * @param packageName Package of accessibility service 55 * @param serviceName Class of accessibility service 56 * @param activityName Class of accessibility service settings activity 57 * @param label Screen title 58 */ prepareArgs(@onNull Bundle args, String packageName, String serviceName, String activityName, String label)59 public static void prepareArgs(@NonNull Bundle args, String packageName, String serviceName, 60 String activityName, String label) { 61 args.putString(ARG_PACKAGE_NAME, packageName); 62 args.putString(ARG_SERVICE_NAME, serviceName); 63 args.putString(ARG_SETTINGS_ACTIVITY_NAME, activityName); 64 args.putString(ARG_LABEL, label); 65 } 66 67 @Override onCreatePreferences(Bundle savedInstanceState, String rootKey)68 public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { 69 final Context themedContext = getPreferenceManager().getContext(); 70 final PreferenceScreen screen = 71 getPreferenceManager().createPreferenceScreen(themedContext); 72 screen.setTitle(getArguments().getString(ARG_LABEL)); 73 74 mEnablePref = new SwitchPreference(themedContext); 75 mEnablePref.setTitle(R.string.system_accessibility_status); 76 mEnablePref.setFragment(AccessibilityServiceConfirmationFragment.class.getName()); 77 screen.addPreference(mEnablePref); 78 79 final Preference settingsPref = new Preference(themedContext); 80 settingsPref.setTitle(R.string.system_accessibility_config); 81 final String activityName = getArguments().getString(ARG_SETTINGS_ACTIVITY_NAME); 82 if (!TextUtils.isEmpty(activityName)) { 83 final String packageName = getArguments().getString(ARG_PACKAGE_NAME); 84 settingsPref.setIntent(new Intent(Intent.ACTION_MAIN) 85 .setComponent(new ComponentName(packageName, activityName))); 86 } else { 87 settingsPref.setEnabled(false); 88 } 89 screen.addPreference(settingsPref); 90 91 setPreferenceScreen(screen); 92 } 93 94 @Override onPreferenceTreeClick(Preference preference)95 public boolean onPreferenceTreeClick(Preference preference) { 96 if (preference == mEnablePref) { 97 // Prepare confirmation dialog and reverts switch until result comes back. 98 updateEnablePref(); 99 // Pass to super to launch confirmation dialog. 100 super.onPreferenceTreeClick(preference); 101 return true; 102 } else { 103 return super.onPreferenceTreeClick(preference); 104 } 105 } 106 updateEnablePref()107 private void updateEnablePref() { 108 final String packageName = getArguments().getString(ARG_PACKAGE_NAME); 109 final String serviceName = getArguments().getString(ARG_SERVICE_NAME); 110 final ComponentName serviceComponent = new ComponentName(packageName, serviceName); 111 final Set<ComponentName> enabledServices = 112 AccessibilityUtils.getEnabledServicesFromSettings(getActivity()); 113 final boolean enabled = enabledServices.contains(serviceComponent); 114 mEnablePref.setChecked(enabled); 115 AccessibilityServiceConfirmationFragment.prepareArgs(mEnablePref.getExtras(), 116 new ComponentName(packageName, serviceName), 117 getArguments().getString(ARG_LABEL), !enabled); 118 } 119 120 @Override onResume()121 public void onResume() { 122 super.onResume(); 123 updateEnablePref(); 124 } 125 126 @Override onAccessibilityServiceConfirmed(ComponentName componentName, boolean enabling)127 public void onAccessibilityServiceConfirmed(ComponentName componentName, boolean enabling) { 128 AccessibilityUtils.setAccessibilityServiceState(getActivity(), 129 componentName, enabling); 130 if (mEnablePref != null) { 131 mEnablePref.setChecked(enabling); 132 } 133 } 134 135 @Override getMetricsCategory()136 public int getMetricsCategory() { 137 return MetricsProto.MetricsEvent.ACCESSIBILITY_SERVICE; 138 } 139 140 @Override getPageId()141 protected int getPageId() { 142 // Partial matching of Service's Android componentName for logging a11y services. 143 String serviceName = getArguments().getString(ARG_SERVICE_NAME); 144 if (TextUtils.isEmpty(serviceName)) { 145 return TvSettingsEnums.PAGE_CLASSIC_DEFAULT; 146 } else if (serviceName.contains("TalkBack")) { 147 return TvSettingsEnums.SYSTEM_A11Y_TALKBACK; 148 } else if (serviceName.contains("AccessibilityMenu")) { 149 return TvSettingsEnums.SYSTEM_A11Y_A11Y_MENU; 150 } else if (serviceName.contains("SelectToSpeak")) { 151 return TvSettingsEnums.SYSTEM_A11Y_STS; 152 } else if (serviceName.contains("SwitchAccess")) { 153 return TvSettingsEnums.SYSTEM_A11Y_SWITCH_ACCESS; 154 } else { 155 return TvSettingsEnums.PAGE_CLASSIC_DEFAULT; 156 } 157 } 158 } 159