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