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 18ed69e8a4170f283fe4203ec010042f91822ab698Phil Weaverimport static android.content.DialogInterface.BUTTON_POSITIVE; 19ed69e8a4170f283fe4203ec010042f91822ab698Phil Weaver 20296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.accessibilityservice.AccessibilityServiceInfo; 21296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.app.Activity; 22296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.app.Dialog; 23296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.app.DialogFragment; 24296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.app.Fragment; 25296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.content.ComponentName; 26296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.content.DialogInterface; 272e2dbfe549d6803483d509b62538a875de433151Phil Weaverimport android.os.Binder; 28296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.os.Bundle; 292e2dbfe549d6803483d509b62538a875de433151Phil Weaverimport android.os.IBinder; 30296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.os.UserHandle; 31296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.provider.Settings; 32296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.text.TextUtils; 33296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport android.view.accessibility.AccessibilityManager; 34296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 35296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.internal.logging.nano.MetricsProto.MetricsEvent; 36296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settings.applications.defaultapps.DefaultAppInfo; 37296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settings.applications.defaultapps.DefaultAppPickerFragment; 38296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settings.core.instrumentation.InstrumentedDialogFragment; 39296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settings.widget.RadioButtonPreference; 40296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport com.android.settingslib.accessibility.AccessibilityUtils; 41296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 42296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport java.util.ArrayList; 43296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverimport java.util.List; 44296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 45296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver/** 46296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver * Fragment for picking accessibility shortcut service 47296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver */ 48296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaverpublic class ShortcutServicePickerFragment extends DefaultAppPickerFragment { 49296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 50296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 51296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public int getMetricsCategory() { 52296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE; 53296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 54296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 55296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 56296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver protected List<? extends DefaultAppInfo> getCandidates() { 57296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final AccessibilityManager accessibilityManager = getContext() 58296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver .getSystemService(AccessibilityManager.class); 59296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final List<AccessibilityServiceInfo> installedServices = 60296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver accessibilityManager.getInstalledAccessibilityServiceList(); 61296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final int numInstalledServices = installedServices.size(); 62296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 63296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver List<DefaultAppInfo> candidates = new ArrayList<>(numInstalledServices); 64296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver for (int i = 0; i < numInstalledServices; i++) { 65296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver AccessibilityServiceInfo installedServiceInfo = installedServices.get(i); 66296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver candidates.add(new DefaultAppInfo(mPm, 67296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver UserHandle.myUserId(), 68296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver installedServiceInfo.getComponentName(), 692cc818acceb372fc6d99b8404d52c0128614d723Saige McVea (String) installedServiceInfo.loadSummary(mPm.getPackageManager()), 70296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver true /* enabled */)); 71296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 72296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 73296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return candidates; 74296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 75296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 76296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 77296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver protected String getDefaultKey() { 78296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver String shortcutServiceString = AccessibilityUtils 79296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver .getShortcutTargetServiceComponentNameString(getContext(), UserHandle.myUserId()); 80296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver if (shortcutServiceString != null) { 81296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver ComponentName shortcutName = ComponentName.unflattenFromString(shortcutServiceString); 82296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver if (shortcutName != null) { 83296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return shortcutName.flattenToString(); 84296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 85296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 86296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return null; 87296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 88296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 89296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 90296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver protected boolean setDefaultKey(String key) { 91296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver Settings.Secure.putString(getContext().getContentResolver(), 92296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, key); 93296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return true; 94296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 95296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 96296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 97296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public void onRadioButtonClicked(RadioButtonPreference selected) { 98296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final String selectedKey = selected.getKey(); 99296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 100296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final Activity activity = getActivity(); 101296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver if (TextUtils.isEmpty(selectedKey)) { 102296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver super.onRadioButtonClicked(selected); 103296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } else if (activity != null) { 104296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final DialogFragment fragment = ConfirmationDialogFragment.newInstance( 105296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver this, selectedKey); 106296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver fragment.show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG); 107296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 108296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 109296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 110296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver private void onServiceConfirmed(String serviceKey) { 111296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver onRadioButtonConfirmed(serviceKey); 112296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 113296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 114296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public static class ConfirmationDialogFragment extends InstrumentedDialogFragment 115296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver implements DialogInterface.OnClickListener { 116296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver private static final String EXTRA_KEY = "extra_key"; 117296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver private static final String TAG = "ConfirmationDialogFragment"; 1182e2dbfe549d6803483d509b62538a875de433151Phil Weaver private IBinder mToken; 119296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 120296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public static ConfirmationDialogFragment newInstance(ShortcutServicePickerFragment parent, 121296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver String key) { 122296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment(); 123296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final Bundle argument = new Bundle(); 124296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver argument.putString(EXTRA_KEY, key); 125296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver fragment.setArguments(argument); 126296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver fragment.setTargetFragment(parent, 0); 1272e2dbfe549d6803483d509b62538a875de433151Phil Weaver fragment.mToken = new Binder(); 128296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return fragment; 129296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 130296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 131296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 132296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public int getMetricsCategory() { 133296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE; 134296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 135296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 136296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 137296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public Dialog onCreateDialog(Bundle savedInstanceState) { 138296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final Bundle bundle = getArguments(); 139296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final String key = bundle.getString(EXTRA_KEY); 140296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final ComponentName serviceComponentName = ComponentName.unflattenFromString(key); 141296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final AccessibilityManager accessibilityManager = getActivity() 142296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver .getSystemService(AccessibilityManager.class); 143296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver AccessibilityServiceInfo info = accessibilityManager 144296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver .getInstalledServiceInfoWithComponentName(serviceComponentName); 145296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver return AccessibilityServiceWarning.createCapabilitiesDialog(getActivity(), info, this); 146296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 147296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver 148296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver @Override 149296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver public void onClick(DialogInterface dialog, int which) { 150296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final Fragment fragment = getTargetFragment(); 151ed69e8a4170f283fe4203ec010042f91822ab698Phil Weaver if ((which == BUTTON_POSITIVE) && (fragment instanceof DefaultAppPickerFragment)) { 152296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver final Bundle bundle = getArguments(); 153296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver ((ShortcutServicePickerFragment) fragment).onServiceConfirmed( 154296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver bundle.getString(EXTRA_KEY)); 155296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 156296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 157296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver } 158296b7263ad5f9dfbfbe7833da02a551e3adf84ebPhil Weaver} 159