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