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 */
16package com.android.settings.accessibility;
17
18import android.accessibilityservice.AccessibilityServiceInfo;
19import android.content.ComponentName;
20import android.content.ContentResolver;
21import android.content.Context;
22import android.os.Bundle;
23import android.os.UserHandle;
24import android.provider.Settings;
25import android.support.v14.preference.SwitchPreference;
26import android.support.v7.preference.Preference;
27import android.text.TextUtils;
28import android.view.accessibility.AccessibilityManager;
29import android.widget.Switch;
30
31import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
32import com.android.settings.R;
33import com.android.settings.search.BaseSearchIndexProvider;
34import com.android.settings.search.Indexable;
35import com.android.settingslib.accessibility.AccessibilityUtils;
36
37/**
38 * Settings page for accessibility shortcut
39 */
40public class AccessibilityShortcutPreferenceFragment extends ToggleFeaturePreferenceFragment
41        implements Indexable {
42
43    public static final String SHORTCUT_SERVICE_KEY = "accessibility_shortcut_service";
44    public static final String ON_LOCK_SCREEN_KEY = "accessibility_shortcut_on_lock_screen";
45
46    private Preference mServicePreference;
47    private SwitchPreference mOnLockScreenSwitchPreference;
48
49    @Override
50    public int getMetricsCategory() {
51        return MetricsEvent.ACCESSIBILITY_TOGGLE_GLOBAL_GESTURE;
52    }
53
54    @Override
55    protected int getHelpResource() {
56        return R.string.help_url_accessibility_shortcut;
57    }
58
59    @Override
60    public void onCreate(Bundle savedInstanceState) {
61        super.onCreate(savedInstanceState);
62
63        addPreferencesFromResource(R.xml.accessibility_shortcut_settings);
64        mServicePreference = findPreference(SHORTCUT_SERVICE_KEY);
65        mOnLockScreenSwitchPreference = (SwitchPreference) findPreference(ON_LOCK_SCREEN_KEY);
66        mOnLockScreenSwitchPreference.setOnPreferenceChangeListener((Preference p, Object o) -> {
67            Settings.Secure.putInt(getContentResolver(),
68                    Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN,
69                    ((Boolean) o) ? 1 : 0);
70            return true;
71        });
72        mFooterPreferenceMixin.createFooterPreference()
73                .setTitle(R.string.accessibility_shortcut_description);
74    }
75
76    @Override
77    public void onResume() {
78        super.onResume();
79        updatePreferences();
80    }
81
82    @Override
83    protected void onInstallSwitchBarToggleSwitch() {
84        super.onInstallSwitchBarToggleSwitch();
85        mSwitchBar.addOnSwitchChangeListener((Switch switchView, boolean enabled) -> {
86            Context context = getContext();
87            if (enabled && (getServiceInfo(context) == null)) {
88                // If no service is configured, we'll disable the shortcut shortly. Give the
89                // user a chance to select a service. We'll update the preferences when we resume.
90                Settings.Secure.putInt(
91                        getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1);
92                mServicePreference.setEnabled(true);
93                mServicePreference.performClick();
94            } else {
95                onPreferenceToggled(Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, enabled);
96            }
97        });
98    }
99
100    @Override
101    protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
102        Settings.Secure.putInt(getContentResolver(), preferenceKey, enabled ? 1 : 0);
103        updatePreferences();
104    }
105
106    private void updatePreferences() {
107        ContentResolver cr = getContentResolver();
108        Context context = getContext();
109        mServicePreference.setSummary(getServiceName(context));
110        if (getServiceInfo(context) == null) {
111            // If no service is configured, make sure the overall shortcut is turned off
112            Settings.Secure.putInt(
113                    getContentResolver(), Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 0);
114        }
115        boolean isEnabled = Settings.Secure
116                .getInt(cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ENABLED, 1) == 1;
117        mSwitchBar.setChecked(isEnabled);
118        mOnLockScreenSwitchPreference.setChecked(Settings.Secure.getInt(
119                cr, Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, 0) == 1);
120        // Only enable changing the service and lock screen behavior if the shortcut is on
121        mServicePreference.setEnabled(mToggleSwitch.isChecked());
122        mOnLockScreenSwitchPreference.setEnabled(mToggleSwitch.isChecked());
123    }
124
125    /**
126     * Get the user-visible name of the service currently selected for the shortcut.
127     *
128     * @param context The current context
129     * @return The name of the service or a string saying that none is selected.
130     */
131    public static CharSequence getServiceName(Context context) {
132        AccessibilityServiceInfo shortcutServiceInfo = getServiceInfo(context);
133        if (shortcutServiceInfo != null) {
134            return shortcutServiceInfo.getResolveInfo().loadLabel(context.getPackageManager());
135        }
136        return context.getString(R.string.accessibility_no_service_selected);
137    }
138
139    private static AccessibilityServiceInfo getServiceInfo(Context context) {
140        ComponentName shortcutServiceName = ComponentName.unflattenFromString(
141                AccessibilityUtils.getShortcutTargetServiceComponentNameString(
142                        context, UserHandle.myUserId()));
143        return AccessibilityManager.getInstance(context)
144                .getInstalledServiceInfoWithComponentName(shortcutServiceName);
145    }
146
147    public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
148            new BaseSearchIndexProvider() {
149                // This fragment is for details of the shortcut. Only the shortcut itself needs
150                // to be indexed.
151                protected boolean isPageSearchEnabled(Context context) {
152                    return false;
153                }
154            };
155}
156