19c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt/*
29c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * Copyright (C) 2017 The Android Open Source Project
39c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt *
49c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * Licensed under the Apache License, Version 2.0 (the "License");
59c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * you may not use this file except in compliance with the License.
69c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * You may obtain a copy of the License at
79c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt *
89c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt *      http://www.apache.org/licenses/LICENSE-2.0
99c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt *
109c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * Unless required by applicable law or agreed to in writing, software
119c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * distributed under the License is distributed on an "AS IS" BASIS,
129c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * See the License for the specific language governing permissions and
149c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt * limitations under the License.
159c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt */
169c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
179c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtpackage com.android.settings.accessibility;
189c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
19bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardtimport android.accessibilityservice.AccessibilityServiceInfo;
20bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardtimport android.content.ComponentName;
21a92271c26d6cc17529747dad02491078f6914abahjchangliaoimport android.content.ContentResolver;
229c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport android.content.Context;
23875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardtimport android.content.res.Resources;
249c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport android.os.Bundle;
259c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport android.provider.SearchIndexableResource;
269c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport android.provider.Settings;
27a92271c26d6cc17529747dad02491078f6914abahjchangliaoimport android.support.annotation.VisibleForTesting;
289c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport android.support.v7.preference.Preference;
29bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardtimport android.text.TextUtils;
30bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardtimport android.view.accessibility.AccessibilityManager;
319c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
329c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport com.android.internal.logging.nano.MetricsProto.MetricsEvent;
339c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport com.android.settings.R;
340cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhangimport com.android.settings.dashboard.DashboardFragment;
359c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport com.android.settings.search.BaseSearchIndexProvider;
369c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport com.android.settings.search.Indexable;
3717ebdcf6e66f4388c74a4d104486e22ee5ad8d40rafftsaiimport com.android.settings.search.actionbar.SearchMenuController;
3817ebdcf6e66f4388c74a4d104486e22ee5ad8d40rafftsaiimport com.android.settings.support.actionbar.HelpResourceProvider;
399c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
409c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport java.util.Arrays;
419c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardtimport java.util.List;
429c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
43807506b1668b8438a138e1485f27e74de6a3d06crafftsaipublic final class MagnificationPreferenceFragment extends DashboardFragment {
44a92271c26d6cc17529747dad02491078f6914abahjchangliao    @VisibleForTesting
45a92271c26d6cc17529747dad02491078f6914abahjchangliao    static final int ON = 1;
46a92271c26d6cc17529747dad02491078f6914abahjchangliao    @VisibleForTesting
47a92271c26d6cc17529747dad02491078f6914abahjchangliao    static final int OFF = 0;
48807506b1668b8438a138e1485f27e74de6a3d06crafftsai
49807506b1668b8438a138e1485f27e74de6a3d06crafftsai    private static final String TAG = "MagnificationPreferenceFragment";
509c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
519c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    // Settings App preference keys
526ad584877575b4904b9f180c399cf9661be7fd28Matthew Fritze    private static final String PREFERENCE_TITLE_KEY = "magnification_preference_screen_title";
539c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
54bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt    // Pseudo ComponentName used to represent navbar magnification in Settings.Secure.
55bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt    private static final String MAGNIFICATION_COMPONENT_ID =
56bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt            "com.android.server.accessibility.MagnificationController";
57bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt
589c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    private boolean mLaunchedFromSuw = false;
599c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
609c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    @Override
61807506b1668b8438a138e1485f27e74de6a3d06crafftsai    public int getMetricsCategory() {
62807506b1668b8438a138e1485f27e74de6a3d06crafftsai        return MetricsEvent.ACCESSIBILITY_SCREEN_MAGNIFICATION_SETTINGS;
63807506b1668b8438a138e1485f27e74de6a3d06crafftsai    }
64807506b1668b8438a138e1485f27e74de6a3d06crafftsai
65807506b1668b8438a138e1485f27e74de6a3d06crafftsai    @Override
66807506b1668b8438a138e1485f27e74de6a3d06crafftsai    protected String getLogTag() {
67807506b1668b8438a138e1485f27e74de6a3d06crafftsai        return TAG;
689c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    }
699c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
709c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    @Override
71e0b0e9f9025038d72f8129606cc1f432afcb54e0Fan Zhang    public int getHelpResource() {
72179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang        return R.string.help_url_magnification;
73179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang    }
74179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang
75179645eecd1a2321e7dd8992678b47799e60f9e6Fan Zhang    @Override
76807506b1668b8438a138e1485f27e74de6a3d06crafftsai    protected int getPreferenceScreenResId() {
77807506b1668b8438a138e1485f27e74de6a3d06crafftsai        return R.xml.accessibility_magnification_settings;
78807506b1668b8438a138e1485f27e74de6a3d06crafftsai    }
799c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
80807506b1668b8438a138e1485f27e74de6a3d06crafftsai    @Override
81807506b1668b8438a138e1485f27e74de6a3d06crafftsai    public void onAttach(Context context) {
82807506b1668b8438a138e1485f27e74de6a3d06crafftsai        super.onAttach(context);
839c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt        final Bundle args = getArguments();
849c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt        if ((args != null) && args.containsKey(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW)) {
859c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt            mLaunchedFromSuw = args.getBoolean(AccessibilitySettings.EXTRA_LAUNCHED_FROM_SUW);
869c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt        }
87807506b1668b8438a138e1485f27e74de6a3d06crafftsai        use(MagnificationGesturesPreferenceController.class)
88807506b1668b8438a138e1485f27e74de6a3d06crafftsai                .setIsFromSUW(mLaunchedFromSuw);
89807506b1668b8438a138e1485f27e74de6a3d06crafftsai        use(MagnificationNavbarPreferenceController.class)
90807506b1668b8438a138e1485f27e74de6a3d06crafftsai                .setIsFromSUW(mLaunchedFromSuw);
919c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    }
929c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
939c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    @Override
949c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    public boolean onPreferenceTreeClick(Preference preference) {
959c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt        if (mLaunchedFromSuw) {
969c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt            // If invoked from SUW, redirect to fragment instrumented for Vision Settings metrics
979c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt            preference.setFragment(
989c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt                    ToggleScreenMagnificationPreferenceFragmentForSetupWizard.class.getName());
9917ebdcf6e66f4388c74a4d104486e22ee5ad8d40rafftsai            Bundle args = preference.getExtras();
10017ebdcf6e66f4388c74a4d104486e22ee5ad8d40rafftsai            // Copy from AccessibilitySettingsForSetupWizardActivity, hide search and help menu
10117ebdcf6e66f4388c74a4d104486e22ee5ad8d40rafftsai            args.putInt(HelpResourceProvider.HELP_URI_RESOURCE_KEY, 0);
10217ebdcf6e66f4388c74a4d104486e22ee5ad8d40rafftsai            args.putBoolean(SearchMenuController.NEED_SEARCH_ICON_IN_ACTION_BAR, false);
1039c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt        }
1049c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt        return super.onPreferenceTreeClick(preference);
1059c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    }
1069c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
107bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt    static CharSequence getConfigurationWarningStringForSecureSettingsKey(String key,
108bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt            Context context) {
109bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt        if (!Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED.equals(key)) {
110bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt            return null;
111bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt        }
112bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt        if (Settings.Secure.getInt(context.getContentResolver(),
113bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                Settings.Secure.ACCESSIBILITY_DISPLAY_MAGNIFICATION_NAVBAR_ENABLED, 0) == 0) {
114bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt            return null;
115bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt        }
116bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt        final AccessibilityManager am = (AccessibilityManager) context.getSystemService(
117bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                Context.ACCESSIBILITY_SERVICE);
118bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt        final String assignedId = Settings.Secure.getString(context.getContentResolver(),
119bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                Settings.Secure.ACCESSIBILITY_BUTTON_TARGET_COMPONENT);
120bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt        if (!TextUtils.isEmpty(assignedId) && !MAGNIFICATION_COMPONENT_ID.equals(assignedId)) {
121bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt            final ComponentName assignedComponentName = ComponentName.unflattenFromString(
122bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                    assignedId);
123bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt            final List<AccessibilityServiceInfo> activeServices =
124bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                    am.getEnabledAccessibilityServiceList(
125bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                            AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
126bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt            final int serviceCount = activeServices.size();
127bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt            for (int i = 0; i < serviceCount; i++) {
128bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                final AccessibilityServiceInfo info = activeServices.get(i);
129bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                if (info.getComponentName().equals(assignedComponentName)) {
130bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                    final CharSequence assignedServiceName = info.getResolveInfo().loadLabel(
131bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                            context.getPackageManager());
132bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                    return context.getString(
133bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                            R.string.accessibility_screen_magnification_navbar_configuration_warning,
134bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                            assignedServiceName);
135bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt                }
1369c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt            }
1379c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt        }
138bc3827d7172955d58c4569fe003eb0d9ee46db1dCasey Burkhardt        return null;
1399c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    }
1409c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt
141a92271c26d6cc17529747dad02491078f6914abahjchangliao    static boolean isChecked(ContentResolver contentResolver, String settingsKey) {
142a92271c26d6cc17529747dad02491078f6914abahjchangliao        return Settings.Secure.getInt(contentResolver, settingsKey, OFF) == ON;
143a92271c26d6cc17529747dad02491078f6914abahjchangliao    }
144a92271c26d6cc17529747dad02491078f6914abahjchangliao
145a92271c26d6cc17529747dad02491078f6914abahjchangliao    static boolean setChecked(ContentResolver contentResolver, String settingsKey,
146a92271c26d6cc17529747dad02491078f6914abahjchangliao            boolean isChecked) {
147a92271c26d6cc17529747dad02491078f6914abahjchangliao        return Settings.Secure.putInt(contentResolver, settingsKey, isChecked ? ON : OFF);
148a92271c26d6cc17529747dad02491078f6914abahjchangliao    }
149a92271c26d6cc17529747dad02491078f6914abahjchangliao
150875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardt    /**
151875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardt     * @return {@code true} if this fragment should be shown, {@code false} otherwise. This
152875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardt     * fragment is shown in the case that more than one magnification mode is available.
153875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardt     */
154875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardt    static boolean isApplicable(Resources res) {
155875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardt        return res.getBoolean(com.android.internal.R.bool.config_showNavigationBar);
156875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardt    }
157875d3b24715c6e36df0f63985d210a4e6280038aCasey Burkhardt
1589c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
1599c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt            new BaseSearchIndexProvider() {
1609c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt                @Override
1619c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt                public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
1629c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt                        boolean enabled) {
1630cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhang                    final SearchIndexableResource sir = new SearchIndexableResource(context);
1640cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhang                    sir.xmlResId = R.xml.accessibility_magnification_settings;
1650cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhang                    return Arrays.asList(sir);
1660cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhang                }
1670cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhang
1680cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhang                @Override
1690cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhang                protected boolean isPageSearchEnabled(Context context) {
1700cd2ccfe3062237036cbdacfeb542f80d8ee6e52Fan Zhang                    return isApplicable(context.getResources());
1719c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt                }
1726ad584877575b4904b9f180c399cf9661be7fd28Matthew Fritze
1736ad584877575b4904b9f180c399cf9661be7fd28Matthew Fritze                @Override
1746ad584877575b4904b9f180c399cf9661be7fd28Matthew Fritze                public List<String> getNonIndexableKeys(Context context) {
1756ad584877575b4904b9f180c399cf9661be7fd28Matthew Fritze                    List<String> keys = super.getNonIndexableKeys(context);
1766ad584877575b4904b9f180c399cf9661be7fd28Matthew Fritze                    keys.add(PREFERENCE_TITLE_KEY);
1776ad584877575b4904b9f180c399cf9661be7fd28Matthew Fritze                    return keys;
1786ad584877575b4904b9f180c399cf9661be7fd28Matthew Fritze                }
1799c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt            };
1809c7143c3e45362e540d1ca99340c65475307455aCasey Burkhardt}
181