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 package com.android.settings.accessibility; 17 18 import static android.content.DialogInterface.BUTTON_POSITIVE; 19 20 import static com.android.settings.Utils.setOverlayAllowed; 21 22 import android.accessibilityservice.AccessibilityServiceInfo; 23 import android.app.Activity; 24 import android.app.Dialog; 25 import android.app.DialogFragment; 26 import android.app.Fragment; 27 import android.content.ComponentName; 28 import android.content.DialogInterface; 29 import android.os.Binder; 30 import android.os.Bundle; 31 import android.os.IBinder; 32 import android.os.UserHandle; 33 import android.provider.Settings; 34 import android.text.TextUtils; 35 import android.view.accessibility.AccessibilityManager; 36 37 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 38 import com.android.settings.applications.defaultapps.DefaultAppInfo; 39 import com.android.settings.applications.defaultapps.DefaultAppPickerFragment; 40 import com.android.settings.core.instrumentation.InstrumentedDialogFragment; 41 import com.android.settings.widget.RadioButtonPreference; 42 import com.android.settingslib.accessibility.AccessibilityUtils; 43 44 import java.util.ArrayList; 45 import java.util.List; 46 47 /** 48 * Fragment for picking accessibility shortcut service 49 */ 50 public class ShortcutServicePickerFragment extends DefaultAppPickerFragment { 51 52 @Override getMetricsCategory()53 public int getMetricsCategory() { 54 return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE; 55 } 56 57 @Override getCandidates()58 protected List<? extends DefaultAppInfo> getCandidates() { 59 final AccessibilityManager accessibilityManager = getContext() 60 .getSystemService(AccessibilityManager.class); 61 final List<AccessibilityServiceInfo> installedServices = 62 accessibilityManager.getInstalledAccessibilityServiceList(); 63 final int numInstalledServices = installedServices.size(); 64 65 List<DefaultAppInfo> candidates = new ArrayList<>(numInstalledServices); 66 for (int i = 0; i < numInstalledServices; i++) { 67 AccessibilityServiceInfo installedServiceInfo = installedServices.get(i); 68 candidates.add(new DefaultAppInfo(mPm, 69 UserHandle.myUserId(), 70 installedServiceInfo.getComponentName(), 71 (String) installedServiceInfo.loadSummary(mPm.getPackageManager()), 72 true /* enabled */)); 73 } 74 75 return candidates; 76 } 77 78 @Override getDefaultKey()79 protected String getDefaultKey() { 80 String shortcutServiceString = AccessibilityUtils 81 .getShortcutTargetServiceComponentNameString(getContext(), UserHandle.myUserId()); 82 if (shortcutServiceString != null) { 83 ComponentName shortcutName = ComponentName.unflattenFromString(shortcutServiceString); 84 if (shortcutName != null) { 85 return shortcutName.flattenToString(); 86 } 87 } 88 return null; 89 } 90 91 @Override setDefaultKey(String key)92 protected boolean setDefaultKey(String key) { 93 Settings.Secure.putString(getContext().getContentResolver(), 94 Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE, key); 95 return true; 96 } 97 98 @Override onRadioButtonClicked(RadioButtonPreference selected)99 public void onRadioButtonClicked(RadioButtonPreference selected) { 100 final String selectedKey = selected.getKey(); 101 102 final Activity activity = getActivity(); 103 if (TextUtils.isEmpty(selectedKey)) { 104 super.onRadioButtonClicked(selected); 105 } else if (activity != null) { 106 final DialogFragment fragment = ConfirmationDialogFragment.newInstance( 107 this, selectedKey); 108 fragment.show(activity.getFragmentManager(), ConfirmationDialogFragment.TAG); 109 } 110 } 111 onServiceConfirmed(String serviceKey)112 private void onServiceConfirmed(String serviceKey) { 113 onRadioButtonConfirmed(serviceKey); 114 } 115 116 public static class ConfirmationDialogFragment extends InstrumentedDialogFragment 117 implements DialogInterface.OnClickListener { 118 private static final String EXTRA_KEY = "extra_key"; 119 private static final String TAG = "ConfirmationDialogFragment"; 120 private IBinder mToken; 121 newInstance(ShortcutServicePickerFragment parent, String key)122 public static ConfirmationDialogFragment newInstance(ShortcutServicePickerFragment parent, 123 String key) { 124 final ConfirmationDialogFragment fragment = new ConfirmationDialogFragment(); 125 final Bundle argument = new Bundle(); 126 argument.putString(EXTRA_KEY, key); 127 fragment.setArguments(argument); 128 fragment.setTargetFragment(parent, 0); 129 fragment.mToken = new Binder(); 130 return fragment; 131 } 132 133 @Override getMetricsCategory()134 public int getMetricsCategory() { 135 return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE; 136 } 137 138 @Override onCreateDialog(Bundle savedInstanceState)139 public Dialog onCreateDialog(Bundle savedInstanceState) { 140 final Bundle bundle = getArguments(); 141 final String key = bundle.getString(EXTRA_KEY); 142 final ComponentName serviceComponentName = ComponentName.unflattenFromString(key); 143 final AccessibilityManager accessibilityManager = getActivity() 144 .getSystemService(AccessibilityManager.class); 145 AccessibilityServiceInfo info = accessibilityManager 146 .getInstalledServiceInfoWithComponentName(serviceComponentName); 147 return AccessibilityServiceWarning.createCapabilitiesDialog(getActivity(), info, this); 148 } 149 150 @Override onResume()151 public void onResume() { 152 super.onResume(); 153 if (mToken != null) { 154 setOverlayAllowed(getActivity(), mToken, false); 155 } 156 } 157 158 @Override onPause()159 public void onPause() { 160 super.onPause(); 161 if (mToken != null) { 162 setOverlayAllowed(getActivity(), mToken, true); 163 } 164 } 165 166 @Override onClick(DialogInterface dialog, int which)167 public void onClick(DialogInterface dialog, int which) { 168 final Fragment fragment = getTargetFragment(); 169 if ((which == BUTTON_POSITIVE) && (fragment instanceof DefaultAppPickerFragment)) { 170 final Bundle bundle = getArguments(); 171 ((ShortcutServicePickerFragment) fragment).onServiceConfirmed( 172 bundle.getString(EXTRA_KEY)); 173 } 174 } 175 } 176 } 177