1a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov/*
2a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * Copyright (C) 2009 The Android Open Source Project
3a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov *
4a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * Licensed under the Apache License, Version 2.0 (the "License");
5a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * you may not use this file except in compliance with the License.
6a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * You may obtain a copy of the License at
7a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov *
8a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov *      http://www.apache.org/licenses/LICENSE-2.0
9a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov *
10a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * Unless required by applicable law or agreed to in writing, software
11a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * distributed under the License is distributed on an "AS IS" BASIS,
12a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * See the License for the specific language governing permissions and
14a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * limitations under the License.
15a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov */
16a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
17a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovpackage com.android.settings;
18a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
196f0b4d8143858e41cede1f935230e2a430b9fd2dSvetoslav Ganovimport android.accessibilityservice.AccessibilityServiceInfo;
20672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.app.ActionBar;
21672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.app.Activity;
2200453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackbornimport android.app.ActivityManagerNative;
23a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.app.AlertDialog;
24cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganovimport android.app.Dialog;
25672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.content.ComponentName;
26672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.content.Context;
27a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.content.DialogInterface;
2805b08a50f86a91ab2db6b7e47febadc593972609Charles Chenimport android.content.Intent;
291a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.content.SharedPreferences;
30232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganovimport android.content.pm.ResolveInfo;
31a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.content.pm.ServiceInfo;
3200453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackbornimport android.content.res.Configuration;
333aa58b0f35c60f7bf4c97a6e12c201abf90824c7Svetoslav Ganovimport android.database.ContentObserver;
3405b08a50f86a91ab2db6b7e47febadc593972609Charles Chenimport android.net.Uri;
35a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.os.Bundle;
36672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.os.Handler;
37672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.os.Message;
3800453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackbornimport android.os.RemoteException;
3905b08a50f86a91ab2db6b7e47febadc593972609Charles Chenimport android.os.SystemProperties;
40a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.preference.CheckBoxPreference;
4182623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganovimport android.preference.ListPreference;
42a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.preference.Preference;
431a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.preference.PreferenceActivity;
446e101d125a9b874ff0337b04c94564ccf95ac7c6David Brownimport android.preference.PreferenceCategory;
45a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.preference.PreferenceScreen;
46a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.provider.Settings;
47a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.text.TextUtils;
48672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.text.TextUtils.SimpleStringSplitter;
49672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.view.Gravity;
506e101d125a9b874ff0337b04c94564ccf95ac7c6David Brownimport android.view.KeyCharacterMap;
516e101d125a9b874ff0337b04c94564ccf95ac7c6David Brownimport android.view.KeyEvent;
52672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.view.Menu;
53672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.view.MenuInflater;
54672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.view.MenuItem;
55672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.view.View;
561a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent;
57a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport android.view.accessibility.AccessibilityManager;
58ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganovimport android.widget.LinearLayout;
59672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.widget.Switch;
60672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport android.widget.TextView;
61a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
62672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport com.android.internal.content.PackageMonitor;
6310fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brownimport com.android.internal.view.RotationPolicy;
64672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport com.android.settings.AccessibilitySettings.ToggleSwitch.OnBeforeCheckedChangeListener;
65672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
66672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport java.util.HashMap;
67a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport java.util.HashSet;
68a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport java.util.List;
69a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganovimport java.util.Map;
70672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolacheimport java.util.Set;
71a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
72a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov/**
73a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov * Activity with the accessibility settings.
74a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov */
7582623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganovpublic class AccessibilitySettings extends SettingsPreferenceFragment implements DialogCreatable,
7682623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov        Preference.OnPreferenceChangeListener {
7705b08a50f86a91ab2db6b7e47febadc593972609Charles Chen    private static final String DEFAULT_SCREENREADER_MARKET_LINK =
7805b08a50f86a91ab2db6b7e47febadc593972609Charles Chen        "market://search?q=pname:com.google.android.marvin.talkback";
7905b08a50f86a91ab2db6b7e47febadc593972609Charles Chen
8000453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackborn    private static final float LARGE_FONT_SCALE = 1.3f;
8100453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackborn
821a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String SYSTEM_PROPERTY_MARKET_URL = "ro.screenreader.market";
831a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
84672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // Timeout before we update the services if packages are added/removed since
85672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // the AccessibilityManagerService has to do that processing first to generate
86672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // the AccessibilityServiceInfo we need for proper presentation.
87232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov    private static final long DELAY_UPDATE_SERVICES_MILLIS = 1000;
88672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
89cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov    private static final char ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR = ':';
90672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
911a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String KEY_INSTALL_ACCESSIBILITY_SERVICE_OFFERED_ONCE =
921a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        "key_install_accessibility_service_offered_once";
931a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
94672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // Preference categories
95672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private static final String SERVICES_CATEGORY = "services_category";
961a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String SYSTEM_CATEGORY = "system_category";
97672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
98672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // Preferences
99672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private static final String TOGGLE_LARGE_TEXT_PREFERENCE = "toggle_large_text_preference";
100672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private static final String TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE =
101672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        "toggle_power_button_ends_call_preference";
1022121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov    private static final String TOGGLE_LOCK_SCREEN_ROTATION_PREFERENCE =
1032121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov        "toggle_lock_screen_rotation_preference";
1047e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov    private static final String TOGGLE_SPEAK_PASSWORD_PREFERENCE =
1057e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov        "toggle_speak_password_preference";
106672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private static final String SELECT_LONG_PRESS_TIMEOUT_PREFERENCE =
107672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        "select_long_press_timeout_preference";
108672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private static final String TOGGLE_SCRIPT_INJECTION_PREFERENCE =
109672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        "toggle_script_injection_preference";
110672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
111672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // Extras passed to sub-fragments.
1121a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String EXTRA_PREFERENCE_KEY = "preference_key";
1131a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String EXTRA_CHECKED = "checked";
1141a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String EXTRA_TITLE = "title";
1151a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String EXTRA_SUMMARY = "summary";
116ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov    private static final String EXTRA_ENABLE_WARNING_TITLE = "enable_warning_title";
117ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov    private static final String EXTRA_ENABLE_WARNING_MESSAGE = "enable_warning_message";
118ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov    private static final String EXTRA_DISABLE_WARNING_TITLE = "disable_warning_title";
119ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov    private static final String EXTRA_DISABLE_WARNING_MESSAGE = "disable_warning_message";
1201a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String EXTRA_SETTINGS_TITLE = "settings_title";
1211a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static final String EXTRA_SETTINGS_COMPONENT_NAME = "settings_component_name";
122672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
123672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // Dialog IDs.
124ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov    private static final int DIALOG_ID_NO_ACCESSIBILITY_SERVICES = 1;
125a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
126672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // Auxiliary members.
127232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov    private final static SimpleStringSplitter sStringColonSplitter =
128cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        new SimpleStringSplitter(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR);
1293d64653d1f8dd58fb05ff845706eda5c7f344d0bSvetoslav Ganov
130232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov    private static final Set<ComponentName> sInstalledServices = new HashSet<ComponentName>();
131232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov
132672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private final Map<String, String> mLongPressTimeoutValuetoTitleMap =
133672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        new HashMap<String, String>();
1346e101d125a9b874ff0337b04c94564ccf95ac7c6David Brown
135672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private final Configuration mCurConfig = new Configuration();
136cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov
137672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private final PackageMonitor mSettingsPackageMonitor = new SettingsPackageMonitor();
13882623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov
139672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private final Handler mHandler = new Handler() {
140672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
141672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void dispatchMessage(Message msg) {
142672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            super.dispatchMessage(msg);
143232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            loadInstalledServices();
144ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            updateServicesPreferences();
145672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
146672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    };
14700453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackborn
14810fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown    private final RotationPolicy.RotationPolicyListener mRotationPolicyListener =
14910fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown            new RotationPolicy.RotationPolicyListener() {
1503aa58b0f35c60f7bf4c97a6e12c201abf90824c7Svetoslav Ganov        @Override
15110fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown        public void onChange() {
15210fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown            updateLockScreenRotationCheckbox();
1533aa58b0f35c60f7bf4c97a6e12c201abf90824c7Svetoslav Ganov        }
1543aa58b0f35c60f7bf4c97a6e12c201abf90824c7Svetoslav Ganov    };
1553aa58b0f35c60f7bf4c97a6e12c201abf90824c7Svetoslav Ganov
156672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    // Preference controls.
157672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private PreferenceCategory mServicesCategory;
1581a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private PreferenceCategory mSystemsCategory;
159672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
160672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private CheckBoxPreference mToggleLargeTextPreference;
161672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private CheckBoxPreference mTogglePowerButtonEndsCallPreference;
1622121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov    private CheckBoxPreference mToggleLockScreenRotationPreference;
1637e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov    private CheckBoxPreference mToggleSpeakPasswordPreference;
164672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private ListPreference mSelectLongPressTimeoutPreference;
1651a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private AccessibilityEnableScriptInjectionPreference mToggleScriptInjectionPreference;
1669b539cc584821761690d1065b309557265582bbfSvetoslav Ganov    private Preference mNoServicesMessagePreference;
1671a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
1681a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private int mLongPressTimeoutDefault;
169a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
170a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov    @Override
171d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani    public void onCreate(Bundle icicle) {
172a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov        super.onCreate(icicle);
173a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov        addPreferencesFromResource(R.xml.accessibility_settings);
1741a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        initializeAllPreferences();
175cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov    }
176cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov
177cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov    @Override
178672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    public void onResume() {
179672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        super.onResume();
180232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov        loadInstalledServices();
181ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        updateAllPreferences();
182ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        if (mServicesCategory.getPreference(0) == mNoServicesMessagePreference) {
1831a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            offerInstallAccessibilitySerivceOnce();
1841a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        }
1850c2cd20d53f6af983e3ba4661804afdc9756de78Dianne Hackborn        mSettingsPackageMonitor.register(getActivity(), getActivity().getMainLooper(), false);
18610fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown        RotationPolicy.registerRotationPolicyListener(getActivity(),
18710fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown                mRotationPolicyListener);
188749ba652279bb4131a1a9dbe3f5d2cc4302c596dSvetoslav Ganov    }
189749ba652279bb4131a1a9dbe3f5d2cc4302c596dSvetoslav Ganov
190749ba652279bb4131a1a9dbe3f5d2cc4302c596dSvetoslav Ganov    @Override
191749ba652279bb4131a1a9dbe3f5d2cc4302c596dSvetoslav Ganov    public void onPause() {
192672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        mSettingsPackageMonitor.unregister();
19310fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown        RotationPolicy.unregisterRotationPolicyListener(getActivity(),
19410fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown                mRotationPolicyListener);
1951a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        super.onPause();
1961a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    }
1971a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
19882623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov    public boolean onPreferenceChange(Preference preference, Object newValue) {
199672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        if (preference == mSelectLongPressTimeoutPreference) {
2001a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            String stringValue = (String) newValue;
20182623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov            Settings.Secure.putInt(getContentResolver(),
2021a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    Settings.Secure.LONG_PRESS_TIMEOUT, Integer.parseInt(stringValue));
203672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mSelectLongPressTimeoutPreference.setSummary(
2041a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    mLongPressTimeoutValuetoTitleMap.get(stringValue));
20582623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov            return true;
20682623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov        }
20782623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov        return false;
20882623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov    }
20982623019d21ceb36aaa9711a4267147883442ce3Svetoslav Ganov
210a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov    @Override
211a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
212672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        if (mToggleLargeTextPreference == preference) {
2131a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            handleToggleLargeTextPreferenceClick();
214672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            return true;
215672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        } else if (mTogglePowerButtonEndsCallPreference == preference) {
2161a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            handleTogglePowerButtonEndsCallPreferenceClick();
217672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            return true;
2182121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov        } else if (mToggleLockScreenRotationPreference == preference) {
2192121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov            handleLockScreenRotationPreferenceClick();
220ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            return true;
2217e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov        } else if (mToggleSpeakPasswordPreference == preference) {
2227e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov            handleToggleSpeakPasswordPreferenceClick();
223a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov        }
224a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov        return super.onPreferenceTreeClick(preferenceScreen, preference);
225a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov    }
226a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
2271a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private void handleToggleLargeTextPreferenceClick() {
228672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        try {
2291a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            mCurConfig.fontScale = mToggleLargeTextPreference.isChecked() ? LARGE_FONT_SCALE : 1;
230672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            ActivityManagerNative.getDefault().updatePersistentConfiguration(mCurConfig);
2311a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        } catch (RemoteException re) {
232672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            /* ignore */
2333d64653d1f8dd58fb05ff845706eda5c7f344d0bSvetoslav Ganov        }
2343d64653d1f8dd58fb05ff845706eda5c7f344d0bSvetoslav Ganov    }
2353d64653d1f8dd58fb05ff845706eda5c7f344d0bSvetoslav Ganov
2361a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private void handleTogglePowerButtonEndsCallPreferenceClick() {
2371a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        Settings.Secure.putInt(getContentResolver(),
2381a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
2391a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                (mTogglePowerButtonEndsCallPreference.isChecked()
2401a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                        ? Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP
2411a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                        : Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_SCREEN_OFF));
242a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov    }
243a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
2442121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov    private void handleLockScreenRotationPreferenceClick() {
24510fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown        RotationPolicy.setRotationLockForAccessibility(getActivity(),
24610fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown                !mToggleLockScreenRotationPreference.isChecked());
2471a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    }
2481a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
2497e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov    private void handleToggleSpeakPasswordPreferenceClick() {
2507e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov        Settings.Secure.putInt(getContentResolver(),
2517e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov                Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD,
2527e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov                mToggleSpeakPasswordPreference.isChecked() ? 1 : 0);
2537e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov    }
2547e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov
2551a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private void initializeAllPreferences() {
256672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        mServicesCategory = (PreferenceCategory) findPreference(SERVICES_CATEGORY);
2571a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        mSystemsCategory = (PreferenceCategory) findPreference(SYSTEM_CATEGORY);
2581a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
2591a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // Large text.
2601a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        mToggleLargeTextPreference =
2611a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            (CheckBoxPreference) findPreference(TOGGLE_LARGE_TEXT_PREFERENCE);
2621a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
2631a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // Power button ends calls.
2641a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        mTogglePowerButtonEndsCallPreference =
2651a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            (CheckBoxPreference) findPreference(TOGGLE_POWER_BUTTON_ENDS_CALL_PREFERENCE);
266ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        if (!KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
267ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                || !Utils.isVoiceCapable(getActivity())) {
2681a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            mSystemsCategory.removePreference(mTogglePowerButtonEndsCallPreference);
2691a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        }
2701a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
2712121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov        // Lock screen rotation.
2722121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov        mToggleLockScreenRotationPreference =
2732121f097c092cace1fb49f9d4b9c12f16ab20ab0Svetoslav Ganov            (CheckBoxPreference) findPreference(TOGGLE_LOCK_SCREEN_ROTATION_PREFERENCE);
274ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
2757e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov        // Speak passwords.
2767e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov        mToggleSpeakPasswordPreference =
2777e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov            (CheckBoxPreference) findPreference(TOGGLE_SPEAK_PASSWORD_PREFERENCE);
2787e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov
2791a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // Long press timeout.
2801a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        mSelectLongPressTimeoutPreference =
2811a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            (ListPreference) findPreference(SELECT_LONG_PRESS_TIMEOUT_PREFERENCE);
282672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        mSelectLongPressTimeoutPreference.setOnPreferenceChangeListener(this);
2831a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        if (mLongPressTimeoutValuetoTitleMap.size() == 0) {
2841a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            String[] timeoutValues = getResources().getStringArray(
2851a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    R.array.long_press_timeout_selector_values);
2861a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            mLongPressTimeoutDefault = Integer.parseInt(timeoutValues[0]);
2871a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            String[] timeoutTitles = getResources().getStringArray(
2881a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    R.array.long_press_timeout_selector_titles);
2891a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            final int timeoutValueCount = timeoutValues.length;
2901a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            for (int i = 0; i < timeoutValueCount; i++) {
2911a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov               mLongPressTimeoutValuetoTitleMap.put(timeoutValues[i], timeoutTitles[i]);
2921a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            }
2931a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        }
2941a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
2951a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // Script injection.
2961a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        mToggleScriptInjectionPreference = (AccessibilityEnableScriptInjectionPreference)
2971a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            findPreference(TOGGLE_SCRIPT_INJECTION_PREFERENCE);
298a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov    }
299a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
300ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov    private void updateAllPreferences() {
301ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        updateServicesPreferences();
302ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        updateSystemPreferences();
3031a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    }
3041a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
305ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov    private void updateServicesPreferences() {
3061a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // Since services category is auto generated we have to do a pass
3071a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // to generate it since services can come and go and then based on
3081a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // the global accessibility state to decided whether it is enabled.
3091a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
3101a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // Generate.
311672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        mServicesCategory.removeAll();
312672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
313672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        AccessibilityManager accessibilityManager = AccessibilityManager.getInstance(getActivity());
314a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
3156f0b4d8143858e41cede1f935230e2a430b9fd2dSvetoslav Ganov        List<AccessibilityServiceInfo> installedServices =
3166f0b4d8143858e41cede1f935230e2a430b9fd2dSvetoslav Ganov            accessibilityManager.getInstalledAccessibilityServiceList();
317cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        Set<ComponentName> enabledServices = getEnabledServicesFromSettings(getActivity());
318a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
319cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        final boolean accessibilityEnabled = Settings.Secure.getInt(getContentResolver(),
320cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov                Settings.Secure.ACCESSIBILITY_ENABLED, 0) == 1;
321a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov
322a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov        for (int i = 0, count = installedServices.size(); i < count; ++i) {
323672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            AccessibilityServiceInfo info = installedServices.get(i);
324672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
325672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            PreferenceScreen preference = getPreferenceManager().createPreferenceScreen(
326672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    getActivity());
327672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            String title = info.getResolveInfo().loadLabel(getPackageManager()).toString();
328672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
329672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            ServiceInfo serviceInfo = info.getResolveInfo().serviceInfo;
330672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            ComponentName componentName = new ComponentName(serviceInfo.packageName,
331672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    serviceInfo.name);
332abc95ee82295b82ad0475a8b4c55a5196a5f014aSvetoslav Ganov
333672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            preference.setKey(componentName.flattenToString());
334672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
335672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            preference.setTitle(title);
336cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov            final boolean serviceEnabled = accessibilityEnabled
337cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov                && enabledServices.contains(componentName);
338cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov            if (serviceEnabled) {
339672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                preference.setSummary(getString(R.string.accessibility_service_state_on));
340672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            } else {
341672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                preference.setSummary(getString(R.string.accessibility_service_state_off));
342672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            }
343672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
344672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            preference.setOrder(i);
345ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            preference.setFragment(ToggleAccessibilityServicePreferenceFragment.class.getName());
3461a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            preference.setPersistent(true);
347672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
348672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            Bundle extras = preference.getExtras();
349672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            extras.putString(EXTRA_PREFERENCE_KEY, preference.getKey());
350cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov            extras.putBoolean(EXTRA_CHECKED, serviceEnabled);
351672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            extras.putString(EXTRA_TITLE, title);
3521a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
35363ad27860b870651bba9cdb713b767727b3a179dSvetoslav Ganov            String description = info.loadDescription(getPackageManager());
3541a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            if (TextUtils.isEmpty(description)) {
3551a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                description = getString(R.string.accessibility_service_default_description);
3561a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            }
3571a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            extras.putString(EXTRA_SUMMARY, description);
3581a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
359ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            CharSequence applicationLabel = info.getResolveInfo().loadLabel(getPackageManager());
360ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
361ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            extras.putString(EXTRA_ENABLE_WARNING_TITLE, getString(
362ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    R.string.accessibility_service_security_warning_title, applicationLabel));
363ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            extras.putString(EXTRA_ENABLE_WARNING_MESSAGE, getString(
364ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    R.string.accessibility_service_security_warning_summary, applicationLabel));
365ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
366ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            extras.putString(EXTRA_DISABLE_WARNING_TITLE, getString(
367ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    R.string.accessibility_service_disable_warning_title,
368ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    applicationLabel));
369ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            extras.putString(EXTRA_DISABLE_WARNING_MESSAGE, getString(
370ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    R.string.accessibility_service_disable_warning_summary,
371ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    applicationLabel));
372672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
373672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            String settingsClassName = info.getSettingsActivityName();
374672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            if (!TextUtils.isEmpty(settingsClassName)) {
375672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                extras.putString(EXTRA_SETTINGS_TITLE,
376672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                        getString(R.string.accessibility_menu_item_settings));
377672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                extras.putString(EXTRA_SETTINGS_COMPONENT_NAME,
378672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                        new ComponentName(info.getResolveInfo().serviceInfo.packageName,
379672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                                settingsClassName).flattenToString());
380cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov            }
381672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
382672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mServicesCategory.addPreference(preference);
383a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov        }
3841a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
385ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        if (mServicesCategory.getPreferenceCount() == 0) {
386ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            if (mNoServicesMessagePreference == null) {
387ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                mNoServicesMessagePreference = new Preference(getActivity()) {
388ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    @Override
389ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    protected void onBindView(View view) {
390ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        super.onBindView(view);
391ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
392ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        LinearLayout containerView =
393ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                            (LinearLayout) view.findViewById(R.id.message_container);
394ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        containerView.setGravity(Gravity.CENTER);
395ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
396ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        TextView summaryView = (TextView) view.findViewById(R.id.summary);
3979b539cc584821761690d1065b309557265582bbfSvetoslav Ganov                        String title = getString(R.string.accessibility_no_services_installed);
398ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        summaryView.setText(title);
399ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    }
400ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                };
401ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                mNoServicesMessagePreference.setPersistent(false);
402ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                mNoServicesMessagePreference.setLayoutResource(
403ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        R.layout.text_description_preference);
404ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                mNoServicesMessagePreference.setSelectable(false);
405ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            }
406ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            mServicesCategory.addPreference(mNoServicesMessagePreference);
407ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        }
408a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov    }
40905b08a50f86a91ab2db6b7e47febadc593972609Charles Chen
410ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov    private void updateSystemPreferences() {
411672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        // Large text.
41200453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackborn        try {
413ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            mCurConfig.updateFrom(ActivityManagerNative.getDefault().getConfiguration());
414672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        } catch (RemoteException re) {
415672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            /* ignore */
41600453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackborn        }
417ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        mToggleLargeTextPreference.setChecked(mCurConfig.fontScale == LARGE_FONT_SCALE);
418672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
4191a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // Power button ends calls.
420ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        if (KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER)
421ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                && Utils.isVoiceCapable(getActivity())) {
422ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            final int incallPowerBehavior = Settings.Secure.getInt(getContentResolver(),
4231a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR,
424ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_DEFAULT);
425ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            final boolean powerButtonEndsCall =
426ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                (incallPowerBehavior == Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP);
427ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            mTogglePowerButtonEndsCallPreference.setChecked(powerButtonEndsCall);
428672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
429672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
430ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        // Auto-rotate screen
43110fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown        updateLockScreenRotationCheckbox();
432ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
4337e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov        // Speak passwords.
4347e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov        final boolean speakPasswordEnabled = Settings.Secure.getInt(getContentResolver(),
4357e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov                Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD, 0) != 0;
4367e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov        mToggleSpeakPasswordPreference.setChecked(speakPasswordEnabled);
4377e8dcbea65356807ca052ee5e98c9b25b7f0b1caSvetoslav Ganov
438672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        // Long press timeout.
439ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        final int longPressTimeout = Settings.Secure.getInt(getContentResolver(),
440ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                Settings.Secure.LONG_PRESS_TIMEOUT, mLongPressTimeoutDefault);
441ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        String value = String.valueOf(longPressTimeout);
442ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        mSelectLongPressTimeoutPreference.setValue(value);
4431a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        mSelectLongPressTimeoutPreference.setSummary(mLongPressTimeoutValuetoTitleMap.get(value));
444672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
445672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        // Script injection.
446ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        final boolean  scriptInjectionAllowed = (Settings.Secure.getInt(getContentResolver(),
447ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                Settings.Secure.ACCESSIBILITY_SCRIPT_INJECTION, 0) == 1);
448ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        mToggleScriptInjectionPreference.setInjectionAllowed(scriptInjectionAllowed);
4491a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    }
4501a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
45110fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown    private void updateLockScreenRotationCheckbox() {
452b5858bbdc363e21bf87ac5643822ec9e57956c52Jeff Brown        Context context = getActivity();
453b5858bbdc363e21bf87ac5643822ec9e57956c52Jeff Brown        if (context != null) {
454b5858bbdc363e21bf87ac5643822ec9e57956c52Jeff Brown            mToggleLockScreenRotationPreference.setChecked(
455b5858bbdc363e21bf87ac5643822ec9e57956c52Jeff Brown                    !RotationPolicy.isRotationLocked(context));
456b5858bbdc363e21bf87ac5643822ec9e57956c52Jeff Brown        }
45710fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown    }
45810fbf52ccb5c6657eef3bbe520c71ff7f729bad3Jeff Brown
4591a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private void offerInstallAccessibilitySerivceOnce() {
4609b539cc584821761690d1065b309557265582bbfSvetoslav Ganov        // There is always one preference - if no services it is just a message.
4619b539cc584821761690d1065b309557265582bbfSvetoslav Ganov        if (mServicesCategory.getPreference(0) != mNoServicesMessagePreference) {
4621a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            return;
4631a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        }
4641a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        SharedPreferences preferences = getActivity().getPreferences(Context.MODE_PRIVATE);
4651a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        final boolean offerInstallService = !preferences.getBoolean(
4661a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                KEY_INSTALL_ACCESSIBILITY_SERVICE_OFFERED_ONCE, false);
4671a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        if (offerInstallService) {
4681a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            preferences.edit().putBoolean(KEY_INSTALL_ACCESSIBILITY_SERVICE_OFFERED_ONCE,
4691a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    true).commit();
4701a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            // Notify user that they do not have any accessibility
4711a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            // services installed and direct them to Market to get TalkBack.
4721a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            showDialog(DIALOG_ID_NO_ACCESSIBILITY_SERVICES);
473672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
47400453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackborn    }
47500453157ae62d3ba63fe42eccf5113d89e15cab7Dianne Hackborn
476cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov    @Override
477cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov    public Dialog onCreateDialog(int dialogId) {
478cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov        switch (dialogId) {
479cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov            case DIALOG_ID_NO_ACCESSIBILITY_SERVICES:
480cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                return new AlertDialog.Builder(getActivity())
481cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                    .setTitle(R.string.accessibility_service_no_apps_title)
482cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                    .setMessage(R.string.accessibility_service_no_apps_message)
483cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                    .setPositiveButton(android.R.string.ok,
484cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                        new DialogInterface.OnClickListener() {
485cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                            public void onClick(DialogInterface dialog, int which) {
486cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                                // dismiss the dialog before launching the activity otherwise
487cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                                // the dialog removal occurs after onSaveInstanceState which
488cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                                // triggers an exception
4891a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                                removeDialog(DIALOG_ID_NO_ACCESSIBILITY_SERVICES);
490cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                                String screenreaderMarketLink = SystemProperties.get(
4911a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                                        SYSTEM_PROPERTY_MARKET_URL,
4921a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                                        DEFAULT_SCREENREADER_MARKET_LINK);
493cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                                Uri marketUri = Uri.parse(screenreaderMarketLink);
494cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                                Intent marketIntent = new Intent(Intent.ACTION_VIEW, marketUri);
495cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                                startActivity(marketIntent);
496cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                            }
497cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                    })
498cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                    .setNegativeButton(android.R.string.cancel, null)
499cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                    .create();
500cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov            default:
501cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov                return null;
502cdd8e34b4fd2a751490b5adfae048563fa14d9d5Svetoslav Ganov        }
50305b08a50f86a91ab2db6b7e47febadc593972609Charles Chen    }
504672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
505232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov    private void loadInstalledServices() {
506232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov        List<AccessibilityServiceInfo> installedServiceInfos =
507232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            AccessibilityManager.getInstance(getActivity())
508232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov                .getInstalledAccessibilityServiceList();
509232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov        Set<ComponentName> installedServices = sInstalledServices;
510232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov        installedServices.clear();
511232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov        final int installedServiceInfoCount = installedServiceInfos.size();
512232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov        for (int i = 0; i < installedServiceInfoCount; i++) {
513232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            ResolveInfo resolveInfo = installedServiceInfos.get(i).getResolveInfo();
514232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            ComponentName installedService = new ComponentName(
515232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov                    resolveInfo.serviceInfo.packageName,
516232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov                    resolveInfo.serviceInfo.name);
517232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            installedServices.add(installedService);
518232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov        }
519232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov    }
520232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov
521cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov    private static Set<ComponentName> getEnabledServicesFromSettings(Context context) {
522cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        String enabledServicesSetting = Settings.Secure.getString(context.getContentResolver(),
523cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
524cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        if (enabledServicesSetting == null) {
525cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov            enabledServicesSetting = "";
526cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        }
527cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        Set<ComponentName> enabledServices = new HashSet<ComponentName>();
528cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        SimpleStringSplitter colonSplitter = sStringColonSplitter;
529cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        colonSplitter.setString(enabledServicesSetting);
530cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        while (colonSplitter.hasNext()) {
531cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov            String componentNameString = colonSplitter.next();
532cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov            ComponentName enabledService = ComponentName.unflattenFromString(
533cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov                    componentNameString);
534cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov            if (enabledService != null) {
535cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov                enabledServices.add(enabledService);
536cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov            }
537cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        }
538cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov        return enabledServices;
539cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov    }
540cb0a7a82a6c747fafd6c46c2949396a0b549a104Svetoslav Ganov
541672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    private class SettingsPackageMonitor extends PackageMonitor {
542672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
543672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
544672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void onPackageAdded(String packageName, int uid) {
545672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            Message message = mHandler.obtainMessage();
546232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            mHandler.sendMessageDelayed(message, DELAY_UPDATE_SERVICES_MILLIS);
547672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
548672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
549672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
550672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void onPackageAppeared(String packageName, int reason) {
551672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            Message message = mHandler.obtainMessage();
552232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            mHandler.sendMessageDelayed(message, DELAY_UPDATE_SERVICES_MILLIS);
553672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
554672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
555672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
556672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void onPackageDisappeared(String packageName, int reason) {
557672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            Message message = mHandler.obtainMessage();
558232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            mHandler.sendMessageDelayed(message, DELAY_UPDATE_SERVICES_MILLIS);
559672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
560672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
561672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
562672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void onPackageRemoved(String packageName, int uid) {
563672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            Message message = mHandler.obtainMessage();
564232d031a13244e8a2a9a56909e9cdaa2b35f6e00Svetoslav Ganov            mHandler.sendMessageDelayed(message, DELAY_UPDATE_SERVICES_MILLIS);
565672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
566672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    }
567672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
5681a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov    private static ToggleSwitch createAndAddActionBarToggleSwitch(Activity activity) {
569672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        ToggleSwitch toggleSwitch = new ToggleSwitch(activity);
570672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        final int padding = activity.getResources().getDimensionPixelSize(
571672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                R.dimen.action_bar_switch_padding);
572672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        toggleSwitch.setPadding(0, 0, padding, 0);
573672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        activity.getActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM,
574672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                ActionBar.DISPLAY_SHOW_CUSTOM);
575672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        activity.getActionBar().setCustomView(toggleSwitch,
576672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                new ActionBar.LayoutParams(ActionBar.LayoutParams.WRAP_CONTENT,
577672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                        ActionBar.LayoutParams.WRAP_CONTENT,
578672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                        Gravity.CENTER_VERTICAL | Gravity.RIGHT));
579672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        return toggleSwitch;
580672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    }
581672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
582672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    public static class ToggleSwitch extends Switch {
583672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
584672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        private OnBeforeCheckedChangeListener mOnBeforeListener;
585672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
586672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public static interface OnBeforeCheckedChangeListener {
587672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked);
588672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
589672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
590672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public ToggleSwitch(Context context) {
591672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            super(context);
592672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
593672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
594672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void setOnBeforeCheckedChangeListener(OnBeforeCheckedChangeListener listener) {
595672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mOnBeforeListener = listener;
596672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
597672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
598672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
599672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void setChecked(boolean checked) {
600672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            if (mOnBeforeListener != null
601672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    && mOnBeforeListener.onBeforeCheckedChanged(this, checked)) {
602672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                return;
603672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            }
604672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            super.setChecked(checked);
605672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
606672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
6071a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        public void setCheckedInternal(boolean checked) {
608672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            super.setChecked(checked);
609672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
610672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    }
611672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
612ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov    public static class ToggleAccessibilityServicePreferenceFragment
613ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            extends SettingsPreferenceFragment implements DialogInterface.OnClickListener {
614672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
615ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        private static final int DIALOG_ID_ENABLE_WARNING = 1;
616ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        private static final int DIALOG_ID_DISABLE_WARNING = 2;
617672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
618672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        private String mPreferenceKey;
619672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
620672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        private ToggleSwitch mToggleSwitch;
621672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
622ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        private CharSequence mEnableWarningTitle;
623ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        private CharSequence mEnableWarningMessage;
624ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        private CharSequence mDisableWarningTitle;
625ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        private CharSequence mDisableWarningMessage;
626ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov
627672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        private Preference mSummaryPreference;
628672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
629672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        private CharSequence mSettingsTitle;
630672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        private Intent mSettingsIntent;
631672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
632ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov        private int mShownDialogId;
633ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
6341a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        // TODO: Showing sub-sub fragment does not handle the activity title
6351a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        //       so we do it but this is wrong. Do a real fix when there is time.
6361a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        private CharSequence mOldActivityTitle;
637672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
638672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
639672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void onCreate(Bundle savedInstanceState) {
640672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            super.onCreate(savedInstanceState);
641672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
642672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    getActivity());
643672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            setPreferenceScreen(preferenceScreen);
644672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mSummaryPreference = new Preference(getActivity()) {
645672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                @Override
646672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                protected void onBindView(View view) {
647672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    super.onBindView(view);
648672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    TextView summaryView = (TextView) view.findViewById(R.id.summary);
649672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    summaryView.setText(getSummary());
6501a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    sendAccessibilityEvent(summaryView);
6511a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                }
6521a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
6531a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                private void sendAccessibilityEvent(View view) {
6541a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    // Since the view is still not attached we create, populate,
6551a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    // and send the event directly since we do not know when it
6561a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    // will be attached and posting commands is not as clean.
6571a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    AccessibilityManager accessibilityManager =
6581a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                        AccessibilityManager.getInstance(getActivity());
6591a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    if (accessibilityManager.isEnabled()) {
6601a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                        AccessibilityEvent event = AccessibilityEvent.obtain();
6611a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                        event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
6621a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                        view.onInitializeAccessibilityEvent(event);
6631a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                        view.dispatchPopulateAccessibilityEvent(event);
6641a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                        accessibilityManager.sendAccessibilityEvent(event);
6651a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                    }
666672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                }
667672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            };
668672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mSummaryPreference.setPersistent(false);
669672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mSummaryPreference.setLayoutResource(R.layout.text_description_preference);
670672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            preferenceScreen.addPreference(mSummaryPreference);
671672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
672672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
6731a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        @Override
6741a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        public void onViewCreated(View view, Bundle savedInstanceState) {
6751a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            super.onViewCreated(view, savedInstanceState);
6761a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            installActionBarToggleSwitch();
6771a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            processArguments();
6781a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            getListView().setDivider(null);
6791a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            getListView().setEnabled(false);
6801a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        }
6811a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
6821a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        @Override
6831a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        public void onDestroyView() {
6841a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            getActivity().getActionBar().setCustomView(null);
6851a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            if (mOldActivityTitle != null) {
6861a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                getActivity().getActionBar().setTitle(mOldActivityTitle);
6871a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            }
6881b52e0d0240040478ebbe9ac2244816c39ddcd4eAmith Yamasani            mToggleSwitch.setOnBeforeCheckedChangeListener(null);
6891a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            super.onDestroyView();
6901a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov        }
6911a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov
692ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov        public void onPreferenceToggled(String preferenceKey, boolean enabled) {
693ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov             // Parse the enabled services.
694ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            Set<ComponentName> enabledServices = getEnabledServicesFromSettings(getActivity());
695ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov
696ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            // Determine enabled services and accessibility state.
697ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            ComponentName toggledService = ComponentName.unflattenFromString(preferenceKey);
698ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            final boolean accessibilityEnabled;
699ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            if (enabled) {
700ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                // Enabling at least one service enables accessibility.
701ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                accessibilityEnabled = true;
702ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                enabledServices.add(toggledService);
703ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            } else {
704ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                // Check how many enabled and installed services are present.
705ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                int enabledAndInstalledServiceCount = 0;
706ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                Set<ComponentName> installedServices = sInstalledServices;
707ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                for (ComponentName enabledService : enabledServices) {
708ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                    if (installedServices.contains(enabledService)) {
709ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                        enabledAndInstalledServiceCount++;
710ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                    }
711ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                }
712ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                // Disabling the last service disables accessibility.
713ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                accessibilityEnabled = enabledAndInstalledServiceCount > 1
714ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                    || (enabledAndInstalledServiceCount == 1
715ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                            && !installedServices.contains(toggledService));
716ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                enabledServices.remove(toggledService);
717ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            }
718ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov
719ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            // Update the enabled services setting.
720ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            StringBuilder enabledServicesBuilder = new StringBuilder();
721ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            // Keep the enabled services even if they are not installed since we have
722ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            // no way to know whether the application restore process has completed.
723ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            // In general the system should be responsible for the clean up not settings.
724ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            for (ComponentName enabledService : enabledServices) {
725ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                enabledServicesBuilder.append(enabledService.flattenToString());
726ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                enabledServicesBuilder.append(ENABLED_ACCESSIBILITY_SERVICES_SEPARATOR);
727ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            }
728ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            final int enabledServicesBuilderLength = enabledServicesBuilder.length();
729ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            if (enabledServicesBuilderLength > 0) {
730ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                enabledServicesBuilder.deleteCharAt(enabledServicesBuilderLength - 1);
731ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            }
732ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            Settings.Secure.putString(getContentResolver(),
733ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
734ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                    enabledServicesBuilder.toString());
735ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov
736ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            // Update accessibility enabled.
737ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov            Settings.Secure.putInt(getContentResolver(),
738ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov                    Settings.Secure.ACCESSIBILITY_ENABLED, accessibilityEnabled ? 1 : 0);
739ec94c78ec82893254a71fc2d7f05c7b32a776a8eSvetoslav Ganov        }
740672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
741672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
742672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
743672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            super.onCreateOptionsMenu(menu, inflater);
744672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            MenuItem menuItem = menu.add(mSettingsTitle);
745ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            menuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
746672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            menuItem.setIntent(mSettingsIntent);
747672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
748672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
749672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
750672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public Dialog onCreateDialog(int dialogId) {
751ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            CharSequence title = null;
752ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            CharSequence message = null;
753672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            switch (dialogId) {
754ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                case DIALOG_ID_ENABLE_WARNING:
755ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    mShownDialogId = DIALOG_ID_ENABLE_WARNING;
756ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    title = mEnableWarningTitle;
757ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    message = mEnableWarningMessage;
758ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    break;
759ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                case DIALOG_ID_DISABLE_WARNING:
760ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    mShownDialogId = DIALOG_ID_DISABLE_WARNING;
761ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    title = mDisableWarningTitle;
762ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    message = mDisableWarningMessage;
763ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    break;
764672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                default:
765672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    throw new IllegalArgumentException();
766672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            }
767ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            return new AlertDialog.Builder(getActivity())
768ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                .setTitle(title)
769ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                .setIcon(android.R.drawable.ic_dialog_alert)
770ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                .setMessage(message)
771ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                .setCancelable(true)
772ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                .setPositiveButton(android.R.string.ok, this)
773ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                .setNegativeButton(android.R.string.cancel, this)
774ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                .create();
775672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
776672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
777672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        @Override
778672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        public void onClick(DialogInterface dialog, int which) {
779ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            final boolean checked;
780672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            switch (which) {
781672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                case DialogInterface.BUTTON_POSITIVE:
782ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    checked = (mShownDialogId == DIALOG_ID_ENABLE_WARNING);
783ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    mToggleSwitch.setCheckedInternal(checked);
78496832f8cced282a1bca1bb7e4b1325cfa64f380dSvetoslav Ganov                    getArguments().putBoolean(EXTRA_CHECKED, checked);
785ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    onPreferenceToggled(mPreferenceKey, checked);
786672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    break;
787672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                case DialogInterface.BUTTON_NEGATIVE:
788ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    checked = (mShownDialogId == DIALOG_ID_DISABLE_WARNING);
789ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    mToggleSwitch.setCheckedInternal(checked);
79096832f8cced282a1bca1bb7e4b1325cfa64f380dSvetoslav Ganov                    getArguments().putBoolean(EXTRA_CHECKED, checked);
791ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    onPreferenceToggled(mPreferenceKey, checked);
792672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    break;
793672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                default:
794672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    throw new IllegalArgumentException();
795672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            }
796672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
797672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
798672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        private void installActionBarToggleSwitch() {
7991a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            mToggleSwitch = createAndAddActionBarToggleSwitch(getActivity());
800672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mToggleSwitch.setOnBeforeCheckedChangeListener(new OnBeforeCheckedChangeListener() {
801672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                @Override
802672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                public boolean onBeforeCheckedChanged(ToggleSwitch toggleSwitch, boolean checked) {
803672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    if (checked) {
804ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        if (!TextUtils.isEmpty(mEnableWarningMessage)) {
8051a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                            toggleSwitch.setCheckedInternal(false);
80696832f8cced282a1bca1bb7e4b1325cfa64f380dSvetoslav Ganov                            getArguments().putBoolean(EXTRA_CHECKED, false);
807ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                            showDialog(DIALOG_ID_ENABLE_WARNING);
808672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                            return true;
809672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                        }
810672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                        onPreferenceToggled(mPreferenceKey, true);
811672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    } else {
812ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        if (!TextUtils.isEmpty(mDisableWarningMessage)) {
813ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                            toggleSwitch.setCheckedInternal(true);
81496832f8cced282a1bca1bb7e4b1325cfa64f380dSvetoslav Ganov                            getArguments().putBoolean(EXTRA_CHECKED, true);
815ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                            showDialog(DIALOG_ID_DISABLE_WARNING);
816ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                            return true;
817ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                        }
818672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                        onPreferenceToggled(mPreferenceKey, false);
819672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    }
820672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    return false;
821672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                }
822672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            });
823672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
824672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
825672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        private void processArguments() {
826672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            Bundle arguments = getArguments();
827672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
828672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            // Key.
829672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mPreferenceKey = arguments.getString(EXTRA_PREFERENCE_KEY);
830672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
831672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            // Enabled.
832672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            final boolean enabled = arguments.getBoolean(EXTRA_CHECKED);
8331a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            mToggleSwitch.setCheckedInternal(enabled);
834672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
835672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            // Title.
8361a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            PreferenceActivity activity = (PreferenceActivity) getActivity();
8371a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            if (!activity.onIsMultiPane() || activity.onIsHidingHeaders()) {
8381a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                mOldActivityTitle = getActivity().getTitle();
8391a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov                String title = arguments.getString(EXTRA_TITLE);
840ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                getActivity().getActionBar().setTitle(title);
8411a97fa13d03d0966ccaa1480c33d8bedce734407Svetoslav Ganov            }
842672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
843672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            // Summary.
844672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            String summary = arguments.getString(EXTRA_SUMMARY);
845672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            mSummaryPreference.setSummary(summary);
846672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
847672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            // Settings title and intent.
848672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            String settingsTitle = arguments.getString(EXTRA_SETTINGS_TITLE);
849672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            String settingsComponentName = arguments.getString(EXTRA_SETTINGS_COMPONENT_NAME);
850672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            if (!TextUtils.isEmpty(settingsTitle) && !TextUtils.isEmpty(settingsComponentName)) {
851672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                Intent settingsIntent = new Intent(Intent.ACTION_MAIN).setComponent(
852672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                        ComponentName.unflattenFromString(settingsComponentName.toString()));
853672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                if (!getPackageManager().queryIntentActivities(settingsIntent, 0).isEmpty()) {
854672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    mSettingsTitle = settingsTitle;
855672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    mSettingsIntent = settingsIntent;
856672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                    setHasOptionsMenu(true);
857672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache                }
858672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache            }
859672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache
860ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            // Enable warning title.
861ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            mEnableWarningTitle = arguments.getCharSequence(
862ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    AccessibilitySettings.EXTRA_ENABLE_WARNING_TITLE);
863ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
864ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            // Enable warning message.
865ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            mEnableWarningMessage = arguments.getCharSequence(
866ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    AccessibilitySettings.EXTRA_ENABLE_WARNING_MESSAGE);
867ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
868ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            // Disable warning title.
869ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            mDisableWarningTitle = arguments.getString(
870ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    AccessibilitySettings.EXTRA_DISABLE_WARNING_TITLE);
871ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov
872ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            // Disable warning message.
873ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov            mDisableWarningMessage = arguments.getString(
874ea5a50a708389b8ff0d898ffe080149d14377b07Svetoslav Ganov                    AccessibilitySettings.EXTRA_DISABLE_WARNING_MESSAGE);
875672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache        }
876672b3c6576efa9e8e4ad0ebbea7f0c36ecf77d9bCostin Manolache    }
877a05d0dc67eb6aae169308dda25fe235226fa395bsvetoslavganov}
878