1afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/*
2afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
4afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * you may not use this file except in compliance with the License.
6afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * You may obtain a copy of the License at
7afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
8afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project *
10afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * See the License for the specific language governing permissions and
14afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * limitations under the License.
15afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
16afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
17afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectpackage com.android.settings;
18afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
19afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
2086624a21540e2cd336573a55adb5d3997e4a717dJim Millerimport static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
2186624a21540e2cd336573a55adb5d3997e4a717dJim Miller
22487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millettimport android.app.Activity;
232c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunneimport android.app.AlertDialog;
244037c7f27c849a1ada0980ad881636fc940a0b85Dianne Hackbornimport android.app.admin.DevicePolicyManager;
25abc3dc64cf61c9f5c28b6f2640b221d63cb86a0aDianne Hackbornimport android.content.Context;
262c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunneimport android.content.DialogInterface;
27afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.content.Intent;
28bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich canningsimport android.content.pm.PackageManager;
29bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich canningsimport android.content.pm.ResolveInfo;
30783ea85bec4ec3b2f0fa9dd06cf065e527daf04cJim Millerimport android.content.pm.UserInfo;
31afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.os.Bundle;
32bb06a427eb471227cf42a8078a54ca0581309493Dianne Hackbornimport android.os.UserHandle;
33783ea85bec4ec3b2f0fa9dd06cf065e527daf04cJim Millerimport android.os.UserManager;
34afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.preference.CheckBoxPreference;
3586624a21540e2cd336573a55adb5d3997e4a717dJim Millerimport android.preference.ListPreference;
36afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.preference.Preference;
37f8b25796f0ce1096a95cae2b51d07d96e148277cMathew Inwoodimport android.preference.Preference.OnPreferenceChangeListener;
38f8b25796f0ce1096a95cae2b51d07d96e148277cMathew Inwoodimport android.preference.PreferenceGroup;
39afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.preference.PreferenceScreen;
40afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Projectimport android.provider.Settings;
419cec698a1fbbe5e8d23a96347d4e75003f4b8cb6Chia-chi Yehimport android.security.KeyStore;
4256e1526114639dd7f19ef0aa90defd10756bf22dOscar Montemayorimport android.telephony.TelephonyManager;
4386624a21540e2cd336573a55adb5d3997e4a717dJim Millerimport android.util.Log;
44f06d8698a4a2de1973a25df0c6563bdfcba4eb03Amith Yamasani
45a6a8a1479b970d8a84395453703348fe42d17438Gilles Debunneimport com.android.internal.widget.LockPatternUtils;
46a6a8a1479b970d8a84395453703348fe42d17438Gilles Debunne
4786624a21540e2cd336573a55adb5d3997e4a717dJim Millerimport java.util.ArrayList;
48bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich canningsimport java.util.List;
495ed2c4ad43f2c3c85a025da04becd2eaa75927a1Mike Lockwood
50afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project/**
51afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project * Gesture lock pattern settings.
52afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project */
5336972bb7e952ca8a7bd8e57e32246d60873d7479Jim Millerpublic class SecuritySettings extends SettingsPreferenceFragment
542c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        implements OnPreferenceChangeListener, DialogInterface.OnClickListener {
558666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani
568227e303850d7c1162c62947b70d0592432b455eMichael Jurka    static final String TAG = "SecuritySettings";
576f8fb436178d12d11d6ab59671168f0603bdbdcbJason parks
58afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    // Lock Settings
5991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change";
60487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett    private static final String KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING =
61487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett            "biometric_weak_improve_matching";
62a87a25bdec7b991bfa6ef3ea9dfacd0ed162044eDanielle Millett    private static final String KEY_BIOMETRIC_WEAK_LIVELINESS = "biometric_weak_liveliness";
63afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_LOCK_ENABLED = "lockenabled";
64afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private static final String KEY_VISIBLE_PATTERN = "visiblepattern";
65edac9af662f01026fd2b4acf263e1b5d1dfdeaa9Amith Yamasani    private static final String KEY_SECURITY_CATEGORY = "security_category";
66f04211443e9cae815ad89f821b6ec83ec2790c0crich cannings    private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category";
6791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
688666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani    private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
6991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private static final int SET_OR_CHANGE_LOCK_METHOD_REQUEST = 123;
70790e0c3ef3f11d7472ad676ce8314a73df190190Danielle Millett    private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST = 124;
714a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett    private static final int CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF = 125;
727031ab0d756327496ac3ce1e082b53c94be2f3b1Hung-ying Tyan
7391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    // Misc Settings
7491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private static final String KEY_SIM_LOCK = "sim_lock";
7591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private static final String KEY_SHOW_PASSWORD = "show_password";
76028634b6af87665c5d62b0aee669ce376cef065dKenny Root    private static final String KEY_CREDENTIAL_STORAGE_TYPE = "credential_storage_type";
7791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private static final String KEY_RESET_CREDENTIALS = "reset_credentials";
782c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    private static final String KEY_TOGGLE_INSTALL_APPLICATIONS = "toggle_install_applications";
79d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings    private static final String KEY_TOGGLE_VERIFY_APPLICATIONS = "toggle_verify_applications";
80071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller    private static final String KEY_POWER_INSTANTLY_LOCKS = "power_button_instantly_locks";
817fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani    private static final String KEY_CREDENTIALS_MANAGER = "credentials_management";
8279b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler    private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access";
83bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings    private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
8447d380f1e6c823cea444004cb799d4c791145cc6Jim Miller
8555dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock    private PackageManager mPM;
86abc3dc64cf61c9f5c28b6f2640b221d63cb86a0aDianne Hackborn    DevicePolicyManager mDPM;
87122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller
8800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller    private ChooseLockSettingsHelper mChooseLockSettingsHelper;
89122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller    private LockPatternUtils mLockPatternUtils;
9086624a21540e2cd336573a55adb5d3997e4a717dJim Miller    private ListPreference mLockAfter;
9136972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller
924a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett    private CheckBoxPreference mBiometricWeakLiveliness;
9391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private CheckBoxPreference mVisiblePattern;
9491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
9591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private CheckBoxPreference mShowPassword;
9691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
97028634b6af87665c5d62b0aee669ce376cef065dKenny Root    private KeyStore mKeyStore;
9891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private Preference mResetCredentials;
995ed2c4ad43f2c3c85a025da04becd2eaa75927a1Mike Lockwood
1002c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    private CheckBoxPreference mToggleAppInstallation;
1012c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    private DialogInterface mWarnInstallApps;
102d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings    private CheckBoxPreference mToggleVerifyApps;
103071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller    private CheckBoxPreference mPowerButtonInstantlyLocks;
1042c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne
10579b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler    private Preference mNotificationAccess;
10679b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler
1077fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani    private boolean mIsPrimary;
1087fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani
109afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
110d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani    public void onCreate(Bundle savedInstanceState) {
111afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onCreate(savedInstanceState);
112122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller
113d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        mLockPatternUtils = new LockPatternUtils(getActivity());
114afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
11555dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock        mPM = getActivity().getPackageManager();
116abc3dc64cf61c9f5c28b6f2640b221d63cb86a0aDianne Hackborn        mDPM = (DevicePolicyManager)getSystemService(Context.DEVICE_POLICY_SERVICE);
117122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller
118d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani        mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
11902cf71a5916d1b0155e8fff3f62987cdc5c2b7c3Amith Yamasani    }
1205ed2c4ad43f2c3c85a025da04becd2eaa75927a1Mike Lockwood
121afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private PreferenceScreen createPreferenceHierarchy() {
12291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        PreferenceScreen root = getPreferenceScreen();
123122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        if (root != null) {
124122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller            root.removeAll();
125122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        }
126122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        addPreferencesFromResource(R.xml.security_settings);
12791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        root = getPreferenceScreen();
128122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller
12936972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller        // Add options for lock/unlock screen
13036972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller        int resid = 0;
131122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        if (!mLockPatternUtils.isSecure()) {
132783ea85bec4ec3b2f0fa9dd06cf065e527daf04cJim Miller            // if there are multiple users, disable "None" setting
133783ea85bec4ec3b2f0fa9dd06cf065e527daf04cJim Miller            UserManager mUm = (UserManager) getSystemService(Context.USER_SERVICE);
134783ea85bec4ec3b2f0fa9dd06cf065e527daf04cJim Miller            List<UserInfo> users = mUm.getUsers(true);
135783ea85bec4ec3b2f0fa9dd06cf065e527daf04cJim Miller            final boolean singleUser = users.size() == 1;
136783ea85bec4ec3b2f0fa9dd06cf065e527daf04cJim Miller
137783ea85bec4ec3b2f0fa9dd06cf065e527daf04cJim Miller            if (singleUser && mLockPatternUtils.isLockScreenDisabled()) {
13836972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller                resid = R.xml.security_settings_lockscreen;
13936972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller            } else {
14036972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller                resid = R.xml.security_settings_chooser;
14136972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller            }
1420fb158a685d753682afdcffb0b783be8e38e0f2bDanielle Millett        } else if (mLockPatternUtils.usingBiometricWeak() &&
1430fb158a685d753682afdcffb0b783be8e38e0f2bDanielle Millett                mLockPatternUtils.isBiometricWeakInstalled()) {
1445541a86efe5f26956e54de49c4a59bf1dab79a78Jim Miller            resid = R.xml.security_settings_biometric_weak;
145122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        } else {
146af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller            switch (mLockPatternUtils.getKeyguardStoredPasswordQuality()) {
147af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller                case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
14836972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller                    resid = R.xml.security_settings_pattern;
149af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller                    break;
150af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller                case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC:
15136972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller                    resid = R.xml.security_settings_pin;
152af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller                    break;
153af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller                case DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC:
154af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller                case DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC:
15557fbf694a53afb9c1924d81272179dceb3acfa4dKonstantin Lopyrev                case DevicePolicyManager.PASSWORD_QUALITY_COMPLEX:
15636972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller                    resid = R.xml.security_settings_password;
157af366a3ed66dcb3c3ecb1dd101e5d8869b518598Jim Miller                    break;
15800d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller            }
159122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        }
16036972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller        addPreferencesFromResource(resid);
161122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller
1624112199ed654f8bd1cea2c9a29a24be3c148b2edJason parks
1634112199ed654f8bd1cea2c9a29a24be3c148b2edJason parks        // Add options for device encryption
164f8217304073b5cd13823a0602568394be93bf310Jason parks        DevicePolicyManager dpm =
165f8217304073b5cd13823a0602568394be93bf310Jason parks                (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
1664112199ed654f8bd1cea2c9a29a24be3c148b2edJason parks
1677fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani        mIsPrimary = UserHandle.myUserId() == UserHandle.USER_OWNER;
1687fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani
1698666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani        if (!mIsPrimary) {
1708666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani            // Rename owner info settings
1718666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani            Preference ownerInfoPref = findPreference(KEY_OWNER_INFO_SETTINGS);
1728666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani            if (ownerInfoPref != null) {
173b0171715876b672c94c8a5aaafde95ff47b234b4Amith Yamasani                if (UserManager.get(getActivity()).isLinkedUser()) {
174b0171715876b672c94c8a5aaafde95ff47b234b4Amith Yamasani                    ownerInfoPref.setTitle(R.string.profile_info_settings_title);
175b0171715876b672c94c8a5aaafde95ff47b234b4Amith Yamasani                } else {
176b0171715876b672c94c8a5aaafde95ff47b234b4Amith Yamasani                    ownerInfoPref.setTitle(R.string.user_info_settings_title);
177b0171715876b672c94c8a5aaafde95ff47b234b4Amith Yamasani                }
1788666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani            }
1798666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani        }
1808666b9e170c23a9595d611a49b7c8262e357ced1Amith Yamasani
1817fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani        if (mIsPrimary) {
182b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani            switch (dpm.getStorageEncryptionStatus()) {
183b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani            case DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE:
184b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani                // The device is currently encrypted.
185b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani                addPreferencesFromResource(R.xml.security_settings_encrypted);
186b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani                break;
187b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani            case DevicePolicyManager.ENCRYPTION_STATUS_INACTIVE:
188b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani                // This device supports encryption but isn't encrypted.
189b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani                addPreferencesFromResource(R.xml.security_settings_unencrypted);
190b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani                break;
191b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani            }
1924112199ed654f8bd1cea2c9a29a24be3c148b2edJason parks        }
1934112199ed654f8bd1cea2c9a29a24be3c148b2edJason parks
19486624a21540e2cd336573a55adb5d3997e4a717dJim Miller        // lock after preference
19591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT);
19691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        if (mLockAfter != null) {
19791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            setupLockAfterPreference();
19891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            updateLockAfterPreferenceSummary();
19991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
200afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
201a87a25bdec7b991bfa6ef3ea9dfacd0ed162044eDanielle Millett        // biometric weak liveliness
202a87a25bdec7b991bfa6ef3ea9dfacd0ed162044eDanielle Millett        mBiometricWeakLiveliness =
2034a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                (CheckBoxPreference) root.findPreference(KEY_BIOMETRIC_WEAK_LIVELINESS);
204a87a25bdec7b991bfa6ef3ea9dfacd0ed162044eDanielle Millett
205afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        // visible pattern
20691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mVisiblePattern = (CheckBoxPreference) root.findPreference(KEY_VISIBLE_PATTERN);
207afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
208071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller        // lock instantly on power key press
209071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller        mPowerButtonInstantlyLocks = (CheckBoxPreference) root.findPreference(
210071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller                KEY_POWER_INSTANTLY_LOCKS);
211071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller
2128123493ef905a210bd00b0c623459f4c86505298Danielle Millett        // don't display visible pattern if biometric and backup is not pattern
2138123493ef905a210bd00b0c623459f4c86505298Danielle Millett        if (resid == R.xml.security_settings_biometric_weak &&
2148123493ef905a210bd00b0c623459f4c86505298Danielle Millett                mLockPatternUtils.getKeyguardStoredPasswordQuality() !=
2158123493ef905a210bd00b0c623459f4c86505298Danielle Millett                DevicePolicyManager.PASSWORD_QUALITY_SOMETHING) {
2168123493ef905a210bd00b0c623459f4c86505298Danielle Millett            PreferenceGroup securityCategory = (PreferenceGroup)
2178123493ef905a210bd00b0c623459f4c86505298Danielle Millett                    root.findPreference(KEY_SECURITY_CATEGORY);
2188123493ef905a210bd00b0c623459f4c86505298Danielle Millett            if (securityCategory != null && mVisiblePattern != null) {
2198123493ef905a210bd00b0c623459f4c86505298Danielle Millett                securityCategory.removePreference(root.findPreference(KEY_VISIBLE_PATTERN));
2208123493ef905a210bd00b0c623459f4c86505298Danielle Millett            }
2218123493ef905a210bd00b0c623459f4c86505298Danielle Millett        }
2228123493ef905a210bd00b0c623459f4c86505298Danielle Millett
22391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        // Append the rest of the settings
22491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        addPreferencesFromResource(R.xml.security_settings_misc);
22591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
2265c68e12493d3c81324179c7c3ba6cd58279d648bAmith Yamasani        // Do not display SIM lock for devices without an Icc card
227cd05e8859599658a546b5d4ee09068dd2833b901Wink Saville        TelephonyManager tm = TelephonyManager.getDefault();
2287fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani        if (!mIsPrimary || !tm.hasIccCard()) {
22991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            root.removePreference(root.findPreference(KEY_SIM_LOCK));
230a98c353f8b18607f0c2e9af26b91bf6ffbe8dc78Kazuhiro Ondo        } else {
231a98c353f8b18607f0c2e9af26b91bf6ffbe8dc78Kazuhiro Ondo            // Disable SIM lock if sim card is missing or unknown
232a98c353f8b18607f0c2e9af26b91bf6ffbe8dc78Kazuhiro Ondo            if ((TelephonyManager.getDefault().getSimState() ==
233a98c353f8b18607f0c2e9af26b91bf6ffbe8dc78Kazuhiro Ondo                                 TelephonyManager.SIM_STATE_ABSENT) ||
234a98c353f8b18607f0c2e9af26b91bf6ffbe8dc78Kazuhiro Ondo                (TelephonyManager.getDefault().getSimState() ==
235a98c353f8b18607f0c2e9af26b91bf6ffbe8dc78Kazuhiro Ondo                                 TelephonyManager.SIM_STATE_UNKNOWN)) {
236a98c353f8b18607f0c2e9af26b91bf6ffbe8dc78Kazuhiro Ondo                root.findPreference(KEY_SIM_LOCK).setEnabled(false);
237a98c353f8b18607f0c2e9af26b91bf6ffbe8dc78Kazuhiro Ondo            }
238386278a338d740dce95b7fa1514662b0eb5683e4Chouting Zhang        }
239afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
24091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        // Show password
24191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mShowPassword = (CheckBoxPreference) root.findPreference(KEY_SHOW_PASSWORD);
242feff65213231ba6a0f6185f98e660042b5b14595Dianne Hackborn
243c5550c2012c505dfb27d9a8da8ecb4787f366283Kenny Root        // Credential storage
24411bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier        final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
24511bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier        if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
24611bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier            mKeyStore = KeyStore.getInstance();
24711bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier            Preference credentialStorageType = root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE);
248028634b6af87665c5d62b0aee669ce376cef065dKenny Root
24911bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier            final int storageSummaryRes =
250c5550c2012c505dfb27d9a8da8ecb4787f366283Kenny Root                mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware
251c5550c2012c505dfb27d9a8da8ecb4787f366283Kenny Root                        : R.string.credential_storage_type_software;
25211bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier            credentialStorageType.setSummary(storageSummaryRes);
253028634b6af87665c5d62b0aee669ce376cef065dKenny Root
25411bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier            mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS);
25511bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier        } else {
25611bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier            removePreference(KEY_CREDENTIALS_MANAGER);
25711bd33a564d4ae9a48195ad11dbbd09d80e59b55Emily Bernier        }
2588877f74901b456d45aaf7a47f6d2208fab9e283cOscar Montemayor
259c5550c2012c505dfb27d9a8da8ecb4787f366283Kenny Root        // Application install
2600c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall        PreferenceGroup deviceAdminCategory= (PreferenceGroup)
2610c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall                root.findPreference(KEY_DEVICE_ADMIN_CATEGORY);
2622c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        mToggleAppInstallation = (CheckBoxPreference) findPreference(
2632c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                KEY_TOGGLE_INSTALL_APPLICATIONS);
2642c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        mToggleAppInstallation.setChecked(isNonMarketAppsAllowed());
2652c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne
2660c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall        // Side loading of apps.
2671bad7141b4c602399beaddde49ac295ae1a89afcAmith Yamasani        mToggleAppInstallation.setEnabled(mIsPrimary);
2680c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall
2697fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani        // Package verification, only visible to primary user and if enabled
2707fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani        mToggleVerifyApps = (CheckBoxPreference) findPreference(KEY_TOGGLE_VERIFY_APPLICATIONS);
2717fb4f850eabc017bab6090bf9268cf3fae1e08ebAmith Yamasani        if (mIsPrimary && showVerifierSetting()) {
272bbc3045a265238fd80547dd9bb61f6801a038886rich cannings            if (isVerifierInstalled()) {
273bbc3045a265238fd80547dd9bb61f6801a038886rich cannings                mToggleVerifyApps.setChecked(isVerifyAppsEnabled());
274bbc3045a265238fd80547dd9bb61f6801a038886rich cannings            } else {
275bbc3045a265238fd80547dd9bb61f6801a038886rich cannings                mToggleVerifyApps.setChecked(false);
276bbc3045a265238fd80547dd9bb61f6801a038886rich cannings                mToggleVerifyApps.setEnabled(false);
277bbc3045a265238fd80547dd9bb61f6801a038886rich cannings            }
278f04211443e9cae815ad89f821b6ec83ec2790c0crich cannings        } else {
279f04211443e9cae815ad89f821b6ec83ec2790c0crich cannings            if (deviceAdminCategory != null) {
280f04211443e9cae815ad89f821b6ec83ec2790c0crich cannings                deviceAdminCategory.removePreference(mToggleVerifyApps);
281f04211443e9cae815ad89f821b6ec83ec2790c0crich cannings            } else {
282f04211443e9cae815ad89f821b6ec83ec2790c0crich cannings                mToggleVerifyApps.setEnabled(false);
283f04211443e9cae815ad89f821b6ec83ec2790c0crich cannings            }
2848227e303850d7c1162c62947b70d0592432b455eMichael Jurka        }
2858227e303850d7c1162c62947b70d0592432b455eMichael Jurka
28679b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler        mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS);
28755dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock        if (mNotificationAccess != null) {
28855dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock            final int total = NotificationAccessSettings.getListenersCount(mPM);
28955dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock            if (total == 0) {
29055dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                if (deviceAdminCategory != null) {
29155dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                    deviceAdminCategory.removePreference(mNotificationAccess);
29255dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                }
29355dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock            } else {
29455dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                final int n = getNumEnabledNotificationListeners();
29555dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                if (n == 0) {
29655dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                    mNotificationAccess.setSummary(getResources().getString(
29755dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                            R.string.manage_notification_access_summary_zero));
29855dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                } else {
29955dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                    mNotificationAccess.setSummary(String.format(getResources().getQuantityString(
30055dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                            R.plurals.manage_notification_access_summary_nonzero,
30155dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                            n, n)));
30255dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock                }
30355dbdf68f966d5218a265086f848f60d5a75c13fJohn Spurlock            }
30479b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler        }
30579b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler
306afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return root;
307afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
308afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
30979b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler    private int getNumEnabledNotificationListeners() {
31079b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler        final String flat = Settings.Secure.getString(getContentResolver(),
31179b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
31279b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler        if (flat == null || "".equals(flat)) return 0;
31379b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler        final String[] components = flat.split(":");
31479b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler        return components.length;
31579b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler    }
31679b9bfe56ee4036fbe8d9bcac01260356309ae2fDaniel Sandler
3172c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    private boolean isNonMarketAppsAllowed() {
3185a64c739bfbf644dabd11d5330f577e94d478326Christopher Tate        return Settings.Global.getInt(getContentResolver(),
3195a64c739bfbf644dabd11d5330f577e94d478326Christopher Tate                                      Settings.Global.INSTALL_NON_MARKET_APPS, 0) > 0;
3202c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    }
3212c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne
3222c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    private void setNonMarketAppsAllowed(boolean enabled) {
3230c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall        final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE);
3240c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall        if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)) {
3250c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall            return;
3260c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall        }
3272c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        // Change the system setting
3285a64c739bfbf644dabd11d5330f577e94d478326Christopher Tate        Settings.Global.putInt(getContentResolver(), Settings.Global.INSTALL_NON_MARKET_APPS,
3292c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                                enabled ? 1 : 0);
3302c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    }
3312c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne
332d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings    private boolean isVerifyAppsEnabled() {
333d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings        return Settings.Global.getInt(getContentResolver(),
334d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings                                      Settings.Global.PACKAGE_VERIFIER_ENABLE, 1) > 0;
335d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings    }
336d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings
337bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings    private boolean isVerifierInstalled() {
338bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings        final PackageManager pm = getPackageManager();
339bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings        final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
340bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings        verification.setType(PACKAGE_MIME_TYPE);
341bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings        verification.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
342bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings        final List<ResolveInfo> receivers = pm.queryBroadcastReceivers(verification, 0);
343bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings        return (receivers.size() > 0) ? true : false;
344bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings    }
345bfbdceffe60e20a8db91b54cc81cfe49ea0dd96arich cannings
346bbc3045a265238fd80547dd9bb61f6801a038886rich cannings    private boolean showVerifierSetting() {
347bbc3045a265238fd80547dd9bb61f6801a038886rich cannings        return Settings.Global.getInt(getContentResolver(),
348bbc3045a265238fd80547dd9bb61f6801a038886rich cannings                                      Settings.Global.PACKAGE_VERIFIER_SETTING_VISIBLE, 1) > 0;
349bbc3045a265238fd80547dd9bb61f6801a038886rich cannings    }
350bbc3045a265238fd80547dd9bb61f6801a038886rich cannings
3512c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    private void warnAppInstallation() {
3522c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        // TODO: DialogFragment?
3532c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        mWarnInstallApps = new AlertDialog.Builder(getActivity()).setTitle(
3542c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                getResources().getString(R.string.error_title))
3552c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                .setIcon(com.android.internal.R.drawable.ic_dialog_alert)
3562c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                .setMessage(getResources().getString(R.string.install_all_warning))
3572c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                .setPositiveButton(android.R.string.yes, this)
3582c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                .setNegativeButton(android.R.string.no, null)
3592c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                .show();
3602c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    }
3612c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne
3620c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall    @Override
3632c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    public void onClick(DialogInterface dialog, int which) {
3642c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        if (dialog == mWarnInstallApps && which == DialogInterface.BUTTON_POSITIVE) {
3652c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne            setNonMarketAppsAllowed(true);
366b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani            if (mToggleAppInstallation != null) {
367b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani                mToggleAppInstallation.setChecked(true);
368b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani            }
3692c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        }
3702c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    }
3712c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne
3722c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    @Override
3732c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    public void onDestroy() {
3742c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        super.onDestroy();
3752c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        if (mWarnInstallApps != null) {
3762c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne            mWarnInstallApps.dismiss();
3772c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        }
3782c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne    }
3792c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne
38091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private void setupLockAfterPreference() {
38191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        // Compatible with pre-Froyo
38291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        long currentTimeout = Settings.Secure.getLong(getContentResolver(),
38391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
38491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mLockAfter.setValue(String.valueOf(currentTimeout));
38591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mLockAfter.setOnPreferenceChangeListener(this);
38691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        final long adminTimeout = (mDPM != null ? mDPM.getMaximumTimeToLock(null) : 0);
38791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        final long displayTimeout = Math.max(0,
38891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                Settings.System.getInt(getContentResolver(), SCREEN_OFF_TIMEOUT, 0));
38991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        if (adminTimeout > 0) {
39091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            // This setting is a slave to display timeout when a device policy is enforced.
39191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            // As such, maxLockTimeout = adminTimeout - displayTimeout.
39291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            // If there isn't enough time, shows "immediately" setting.
39391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            disableUnusableTimeouts(Math.max(0, adminTimeout - displayTimeout));
39486624a21540e2cd336573a55adb5d3997e4a717dJim Miller        }
39586624a21540e2cd336573a55adb5d3997e4a717dJim Miller    }
39686624a21540e2cd336573a55adb5d3997e4a717dJim Miller
397c9787070bab332b80676b745a44dd8ee4d72073dJim Miller    private void updateLockAfterPreferenceSummary() {
398c9787070bab332b80676b745a44dd8ee4d72073dJim Miller        // Update summary message with current value
399c9787070bab332b80676b745a44dd8ee4d72073dJim Miller        long currentTimeout = Settings.Secure.getLong(getContentResolver(),
40058bca8f15fbdc9e621b3c259a50ecf41c00e64c3Amith Yamasani                Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 5000);
401c9787070bab332b80676b745a44dd8ee4d72073dJim Miller        final CharSequence[] entries = mLockAfter.getEntries();
402c9787070bab332b80676b745a44dd8ee4d72073dJim Miller        final CharSequence[] values = mLockAfter.getEntryValues();
403c9787070bab332b80676b745a44dd8ee4d72073dJim Miller        int best = 0;
404c9787070bab332b80676b745a44dd8ee4d72073dJim Miller        for (int i = 0; i < values.length; i++) {
405c9787070bab332b80676b745a44dd8ee4d72073dJim Miller            long timeout = Long.valueOf(values[i].toString());
406c9787070bab332b80676b745a44dd8ee4d72073dJim Miller            if (currentTimeout >= timeout) {
407c9787070bab332b80676b745a44dd8ee4d72073dJim Miller                best = i;
408c9787070bab332b80676b745a44dd8ee4d72073dJim Miller            }
409c9787070bab332b80676b745a44dd8ee4d72073dJim Miller        }
41091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mLockAfter.setSummary(getString(R.string.lock_after_timeout_summary, entries[best]));
411c9787070bab332b80676b745a44dd8ee4d72073dJim Miller    }
412c9787070bab332b80676b745a44dd8ee4d72073dJim Miller
41391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    private void disableUnusableTimeouts(long maxTimeout) {
41491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        final CharSequence[] entries = mLockAfter.getEntries();
41591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        final CharSequence[] values = mLockAfter.getEntryValues();
41686624a21540e2cd336573a55adb5d3997e4a717dJim Miller        ArrayList<CharSequence> revisedEntries = new ArrayList<CharSequence>();
41786624a21540e2cd336573a55adb5d3997e4a717dJim Miller        ArrayList<CharSequence> revisedValues = new ArrayList<CharSequence>();
41886624a21540e2cd336573a55adb5d3997e4a717dJim Miller        for (int i = 0; i < values.length; i++) {
41986624a21540e2cd336573a55adb5d3997e4a717dJim Miller            long timeout = Long.valueOf(values[i].toString());
42086624a21540e2cd336573a55adb5d3997e4a717dJim Miller            if (timeout <= maxTimeout) {
42186624a21540e2cd336573a55adb5d3997e4a717dJim Miller                revisedEntries.add(entries[i]);
42286624a21540e2cd336573a55adb5d3997e4a717dJim Miller                revisedValues.add(values[i]);
42386624a21540e2cd336573a55adb5d3997e4a717dJim Miller            }
42486624a21540e2cd336573a55adb5d3997e4a717dJim Miller        }
42586624a21540e2cd336573a55adb5d3997e4a717dJim Miller        if (revisedEntries.size() != entries.length || revisedValues.size() != values.length) {
42691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            mLockAfter.setEntries(
42786624a21540e2cd336573a55adb5d3997e4a717dJim Miller                    revisedEntries.toArray(new CharSequence[revisedEntries.size()]));
42891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            mLockAfter.setEntryValues(
42986624a21540e2cd336573a55adb5d3997e4a717dJim Miller                    revisedValues.toArray(new CharSequence[revisedValues.size()]));
43091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            final int userPreference = Integer.valueOf(mLockAfter.getValue());
43186624a21540e2cd336573a55adb5d3997e4a717dJim Miller            if (userPreference <= maxTimeout) {
43291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                mLockAfter.setValue(String.valueOf(userPreference));
43386624a21540e2cd336573a55adb5d3997e4a717dJim Miller            } else {
43486624a21540e2cd336573a55adb5d3997e4a717dJim Miller                // There will be no highlighted selection since nothing in the list matches
43586624a21540e2cd336573a55adb5d3997e4a717dJim Miller                // maxTimeout. The user can still select anything less than maxTimeout.
43686624a21540e2cd336573a55adb5d3997e4a717dJim Miller                // TODO: maybe append maxTimeout to the list and mark selected.
43786624a21540e2cd336573a55adb5d3997e4a717dJim Miller            }
43886624a21540e2cd336573a55adb5d3997e4a717dJim Miller        }
43991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        mLockAfter.setEnabled(revisedEntries.size() > 0);
44086624a21540e2cd336573a55adb5d3997e4a717dJim Miller    }
44186624a21540e2cd336573a55adb5d3997e4a717dJim Miller
442afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
443d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani    public void onResume() {
444afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onResume();
445afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
44686624a21540e2cd336573a55adb5d3997e4a717dJim Miller        // Make sure we reload the preference hierarchy since some of these settings
44786624a21540e2cd336573a55adb5d3997e4a717dJim Miller        // depend on others...
44886624a21540e2cd336573a55adb5d3997e4a717dJim Miller        createPreferenceHierarchy();
44986624a21540e2cd336573a55adb5d3997e4a717dJim Miller
45000d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller        final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
451a87a25bdec7b991bfa6ef3ea9dfacd0ed162044eDanielle Millett        if (mBiometricWeakLiveliness != null) {
4524a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett            mBiometricWeakLiveliness.setChecked(
4534a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                    lockPatternUtils.isBiometricWeakLivelinessEnabled());
454a87a25bdec7b991bfa6ef3ea9dfacd0ed162044eDanielle Millett        }
455122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        if (mVisiblePattern != null) {
456122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller            mVisiblePattern.setChecked(lockPatternUtils.isVisiblePatternEnabled());
457122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        }
458071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller        if (mPowerButtonInstantlyLocks != null) {
459071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller            mPowerButtonInstantlyLocks.setChecked(lockPatternUtils.getPowerButtonInstantlyLocks());
460071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller        }
4617031ab0d756327496ac3ce1e082b53c94be2f3b1Hung-ying Tyan
462b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani        if (mShowPassword != null) {
463b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani            mShowPassword.setChecked(Settings.System.getInt(getContentResolver(),
464b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani                    Settings.System.TEXT_SHOW_PASSWORD, 1) != 0);
465b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani        }
466b0883cb384fc7ad46e011a72355c9fda924e5b28Hung-ying Tyan
467b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani        if (mResetCredentials != null) {
468c4372c3e3fd2d0be54341973bd72ec618931057cKenny Root            mResetCredentials.setEnabled(!mKeyStore.isEmpty());
469b810a0ddf9dd93a08789aff38901eeab9bfaf812Amith Yamasani        }
470afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
471afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
472afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
473a6a8a1479b970d8a84395453703348fe42d17438Gilles Debunne    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
474afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        final String key = preference.getKey();
475afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
47600d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller        final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
477bbb4afa19f75694c585506b0c091372d60e07ca7Jim Miller        if (KEY_UNLOCK_SET_OR_CHANGE.equals(key)) {
47817e9e1933055b207473b488595b2887bfcaea32eJim Miller            startFragment(this, "com.android.settings.ChooseLockGeneric$ChooseLockGenericFragment",
47917e9e1933055b207473b488595b2887bfcaea32eJim Miller                    SET_OR_CHANGE_LOCK_METHOD_REQUEST, null);
480487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett        } else if (KEY_BIOMETRIC_WEAK_IMPROVE_MATCHING.equals(key)) {
481487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett            ChooseLockSettingsHelper helper =
482487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett                    new ChooseLockSettingsHelper(this.getActivity(), this);
483487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett            if (!helper.launchConfirmationActivity(
484790e0c3ef3f11d7472ad676ce8314a73df190190Danielle Millett                    CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST, null, null)) {
485790e0c3ef3f11d7472ad676ce8314a73df190190Danielle Millett                // If this returns false, it means no password confirmation is required, so
486790e0c3ef3f11d7472ad676ce8314a73df190190Danielle Millett                // go ahead and start improve.
487790e0c3ef3f11d7472ad676ce8314a73df190190Danielle Millett                // Note: currently a backup is required for biometric_weak so this code path
488790e0c3ef3f11d7472ad676ce8314a73df190190Danielle Millett                // can't be reached, but is here in case things change in the future
489790e0c3ef3f11d7472ad676ce8314a73df190190Danielle Millett                startBiometricWeakImprove();
490487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett            }
4914a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett        } else if (KEY_BIOMETRIC_WEAK_LIVELINESS.equals(key)) {
4924a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett            if (isToggled(preference)) {
4934a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                lockPatternUtils.setBiometricWeakLivelinessEnabled(true);
4944a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett            } else {
4954a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                // In this case the user has just unchecked the checkbox, but this action requires
4964a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                // them to confirm their password.  We need to re-check the checkbox until
4974a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                // they've confirmed their password
4984a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                mBiometricWeakLiveliness.setChecked(true);
4994a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                ChooseLockSettingsHelper helper =
5004a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                        new ChooseLockSettingsHelper(this.getActivity(), this);
5014a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                if (!helper.launchConfirmationActivity(
5024a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                                CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF, null, null)) {
5034a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                    // If this returns false, it means no password confirmation is required, so
5044a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                    // go ahead and uncheck it here.
5054a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                    // Note: currently a backup is required for biometric_weak so this code path
5064a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                    // can't be reached, but is here in case things change in the future
5074a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                    lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
5084a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                    mBiometricWeakLiveliness.setChecked(false);
5094a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                }
5104a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett            }
511122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        } else if (KEY_LOCK_ENABLED.equals(key)) {
51200d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller            lockPatternUtils.setLockPatternEnabled(isToggled(preference));
513afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else if (KEY_VISIBLE_PATTERN.equals(key)) {
51400d2476d8fc122b4eef59d6be6f7aa41e9c56fdeJim Miller            lockPatternUtils.setVisiblePatternEnabled(isToggled(preference));
515071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller        } else if (KEY_POWER_INSTANTLY_LOCKS.equals(key)) {
516071742d838f9b0c312af309c87eaf2c444aeeab8Jim Miller            lockPatternUtils.setPowerButtonInstantlyLocks(isToggled(preference));
517afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        } else if (preference == mShowPassword) {
518afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project            Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD,
519afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project                    mShowPassword.isChecked() ? 1 : 0);
5202c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne        } else if (preference == mToggleAppInstallation) {
5212c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne            if (mToggleAppInstallation.isChecked()) {
5222c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                mToggleAppInstallation.setChecked(false);
5232c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                warnAppInstallation();
5242c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne            } else {
5252c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne                setNonMarketAppsAllowed(false);
5262c88a877f88b142fa8fd36c1773ab484b5fd7338Gilles Debunne            }
527d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings        } else if (KEY_TOGGLE_VERIFY_APPLICATIONS.equals(key)) {
528d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings            Settings.Global.putInt(getContentResolver(), Settings.Global.PACKAGE_VERIFIER_ENABLE,
529d5d60655a9c23ba02b5fc1264fb1680f599b3b07rich cannings                    mToggleVerifyApps.isChecked() ? 1 : 0);
53036972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller        } else {
53136972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller            // If we didn't handle it, let preferences handle it.
53236972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller            return super.onPreferenceTreeClick(preferenceScreen, preference);
533afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        }
5344bfdcd3e5fb344cad88feaf4172427f0be53ac2cAmith Yamasani
53536972bb7e952ca8a7bd8e57e32246d60873d7479Jim Miller        return true;
536afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
537afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
538afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    private boolean isToggled(Preference pref) {
539afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        return ((CheckBoxPreference) pref).isChecked();
540afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
541afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project
542afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    /**
543a6a8a1479b970d8a84395453703348fe42d17438Gilles Debunne     * see confirmPatternThenDisableAndClear
544afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project     */
545afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    @Override
546d79934731c8d33f6fc63b21c120b9ffba5d06f54Amith Yamasani    public void onActivityResult(int requestCode, int resultCode, Intent data) {
547afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project        super.onActivityResult(requestCode, resultCode, data);
548790e0c3ef3f11d7472ad676ce8314a73df190190Danielle Millett        if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_IMPROVE_REQUEST &&
549487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett                resultCode == Activity.RESULT_OK) {
550487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett            startBiometricWeakImprove();
551487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett            return;
5524a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett        } else if (requestCode == CONFIRM_EXISTING_FOR_BIOMETRIC_WEAK_LIVELINESS_OFF &&
5534a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett                resultCode == Activity.RESULT_OK) {
5544a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett            final LockPatternUtils lockPatternUtils = mChooseLockSettingsHelper.utils();
5554a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett            lockPatternUtils.setBiometricWeakLivelinessEnabled(false);
5568227e303850d7c1162c62947b70d0592432b455eMichael Jurka            // Setting the mBiometricWeakLiveliness checked value to false is handled when onResume
5578227e303850d7c1162c62947b70d0592432b455eMichael Jurka            // is called by grabbing the value from lockPatternUtils.  We can't set it here
5588227e303850d7c1162c62947b70d0592432b455eMichael Jurka            // because mBiometricWeakLiveliness could be null
5594a3e40d68e8b01871121655456d7a1dfa3312f71Danielle Millett            return;
560487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett        }
561122b6c85a9bc7076eacc388142f8c4fccc5462c9Jim Miller        createPreferenceHierarchy();
562afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project    }
563f06d8698a4a2de1973a25df0c6563bdfcba4eb03Amith Yamasani
5640c5a401a58b30041d5fe712d78fccbd47f5b744dMaggie Benthall    @Override
56586624a21540e2cd336573a55adb5d3997e4a717dJim Miller    public boolean onPreferenceChange(Preference preference, Object value) {
56686624a21540e2cd336573a55adb5d3997e4a717dJim Miller        if (preference == mLockAfter) {
56791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            int timeout = Integer.parseInt((String) value);
56886624a21540e2cd336573a55adb5d3997e4a717dJim Miller            try {
56986624a21540e2cd336573a55adb5d3997e4a717dJim Miller                Settings.Secure.putInt(getContentResolver(),
57091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                        Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, timeout);
57186624a21540e2cd336573a55adb5d3997e4a717dJim Miller            } catch (NumberFormatException e) {
57286624a21540e2cd336573a55adb5d3997e4a717dJim Miller                Log.e("SecuritySettings", "could not persist lockAfter timeout setting", e);
57386624a21540e2cd336573a55adb5d3997e4a717dJim Miller            }
574c9787070bab332b80676b745a44dd8ee4d72073dJim Miller            updateLockAfterPreferenceSummary();
57586624a21540e2cd336573a55adb5d3997e4a717dJim Miller        }
57686624a21540e2cd336573a55adb5d3997e4a717dJim Miller        return true;
57786624a21540e2cd336573a55adb5d3997e4a717dJim Miller    }
578487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett
57993c0ee52cc5709ec7353fee5a01e4dd9000e42d1rich cannings    @Override
58093c0ee52cc5709ec7353fee5a01e4dd9000e42d1rich cannings    protected int getHelpResource() {
58193c0ee52cc5709ec7353fee5a01e4dd9000e42d1rich cannings        return R.string.help_url_security;
58293c0ee52cc5709ec7353fee5a01e4dd9000e42d1rich cannings    }
58393c0ee52cc5709ec7353fee5a01e4dd9000e42d1rich cannings
584487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett    public void startBiometricWeakImprove(){
585487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett        Intent intent = new Intent();
586487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett        intent.setClassName("com.android.facelock", "com.android.facelock.AddToSetup");
587487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett        startActivity(intent);
588487b16f3400b62b79f8108ca669cc3e937c69defDanielle Millett    }
589afc4ab2ffbb8327ddce9907961295a32cbf49d0fThe Android Open Source Project}
590