/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.settings; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.ContentQueryMap; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager.NameNotFoundException; import android.database.Cursor; import android.location.LocationManager; import android.os.Bundle; import android.preference.CheckBoxPreference; import android.preference.EditTextPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceCategory; import android.preference.PreferenceGroup; import android.preference.PreferenceScreen; import android.provider.Settings; import android.security.CertTool; import android.security.Keystore; import android.text.Html; import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.util.Log; import android.view.View; import android.widget.TextView; import android.widget.Toast; import com.android.internal.widget.LockPatternUtils; import android.telephony.TelephonyManager; import java.util.ArrayList; import java.util.List; import java.util.Observable; import java.util.Observer; /** * Gesture lock pattern settings. */ public class SecuritySettings extends PreferenceActivity implements DialogInterface.OnDismissListener, DialogInterface.OnClickListener { // Lock Settings private static final String KEY_LOCK_ENABLED = "lockenabled"; private static final String KEY_VISIBLE_PATTERN = "visiblepattern"; private static final String KEY_TACTILE_FEEDBACK_ENABLED = "tactilefeedback"; private static final int CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE = 55; private static final String PREFS_NAME = "location_prefs"; private static final String PREFS_USE_LOCATION = "use_location"; private LockPatternUtils mLockPatternUtils; private CheckBoxPreference mLockEnabled; private CheckBoxPreference mVisiblePattern; private CheckBoxPreference mTactileFeedback; private Preference mChoosePattern; private CheckBoxPreference mShowPassword; // Location Settings private static final String LOCATION_CATEGORY = "location_category"; private static final String LOCATION_NETWORK = "location_network"; private static final String LOCATION_GPS = "location_gps"; private static final String ASSISTED_GPS = "assisted_gps"; // Credential storage private static final String KEY_CSTOR_TYPE_NAME = "typeName"; private static final String KEY_CSTOR_ITEM = "item"; private static final String KEY_CSTOR_NAMESPACE = "namespace"; private static final String KEY_CSTOR_DESCRIPTION = "description"; private static final int CSTOR_MIN_PASSWORD_LENGTH = 8; private static final int CSTOR_INIT_DIALOG = 1; private static final int CSTOR_CHANGE_PASSWORD_DIALOG = 2; private static final int CSTOR_UNLOCK_DIALOG = 3; private static final int CSTOR_RESET_DIALOG = 4; private static final int CSTOR_NAME_CREDENTIAL_DIALOG = 5; private CstorHelper mCstorHelper = new CstorHelper(); // Vendor specific private static final String GSETTINGS_PROVIDER = "com.google.android.providers.settings"; private static final String USE_LOCATION = "use_location"; private static final String KEY_DONE_USE_LOCATION = "doneLocation"; private CheckBoxPreference mUseLocation; private boolean mOkClicked; private Dialog mUseLocationDialog; private CheckBoxPreference mNetwork; private CheckBoxPreference mGps; private CheckBoxPreference mAssistedGps; // These provide support for receiving notification when Location Manager settings change. // This is necessary because the Network Location Provider can change settings // if the user does not confirm enabling the provider. private ContentQueryMap mContentQueryMap; private final class SettingsObserver implements Observer { public void update(Observable o, Object arg) { updateToggles(); } } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.security_settings); mLockPatternUtils = new LockPatternUtils(getContentResolver()); createPreferenceHierarchy(); mNetwork = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_NETWORK); mGps = (CheckBoxPreference) getPreferenceScreen().findPreference(LOCATION_GPS); mAssistedGps = (CheckBoxPreference) getPreferenceScreen().findPreference(ASSISTED_GPS); mUseLocation = (CheckBoxPreference) getPreferenceScreen().findPreference(USE_LOCATION); // Vendor specific try { if (mUseLocation != null && getPackageManager().getPackageInfo(GSETTINGS_PROVIDER, 0) == null) { ((PreferenceGroup)findPreference(LOCATION_CATEGORY)) .removePreference(mUseLocation); } } catch (NameNotFoundException nnfe) { } updateToggles(); // listen for Location Manager settings changes Cursor settingsCursor = getContentResolver().query(Settings.Secure.CONTENT_URI, null, "(" + Settings.System.NAME + "=?)", new String[]{Settings.Secure.LOCATION_PROVIDERS_ALLOWED}, null); mContentQueryMap = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, null); mContentQueryMap.addObserver(new SettingsObserver()); boolean doneUseLocation = savedInstanceState == null ? false : savedInstanceState.getBoolean(KEY_DONE_USE_LOCATION, true); if (!doneUseLocation && (getIntent().getBooleanExtra("SHOW_USE_LOCATION", false) || savedInstanceState != null)) { showUseLocationDialog(true); } mCstorHelper.handleCstorIntents(getIntent()); } private PreferenceScreen createPreferenceHierarchy() { // Root PreferenceScreen root = this.getPreferenceScreen(); // Inline preferences PreferenceCategory inlinePrefCat = new PreferenceCategory(this); inlinePrefCat.setTitle(R.string.lock_settings_title); root.addPreference(inlinePrefCat); // autolock toggle mLockEnabled = new LockEnabledPref(this); mLockEnabled.setTitle(R.string.lockpattern_settings_enable_title); mLockEnabled.setSummary(R.string.lockpattern_settings_enable_summary); mLockEnabled.setKey(KEY_LOCK_ENABLED); inlinePrefCat.addPreference(mLockEnabled); // visible pattern mVisiblePattern = new CheckBoxPreference(this); mVisiblePattern.setKey(KEY_VISIBLE_PATTERN); mVisiblePattern.setTitle(R.string.lockpattern_settings_enable_visible_pattern_title); inlinePrefCat.addPreference(mVisiblePattern); // tactile feedback mTactileFeedback = new CheckBoxPreference(this); mTactileFeedback.setKey(KEY_TACTILE_FEEDBACK_ENABLED); mTactileFeedback.setTitle(R.string.lockpattern_settings_enable_tactile_feedback_title); inlinePrefCat.addPreference(mTactileFeedback); // change pattern lock Intent intent = new Intent(); intent.setClassName("com.android.settings", "com.android.settings.ChooseLockPatternTutorial"); mChoosePattern = getPreferenceManager().createPreferenceScreen(this); mChoosePattern.setIntent(intent); inlinePrefCat.addPreference(mChoosePattern); int activePhoneType = TelephonyManager.getDefault().getPhoneType(); // do not display SIM lock for CDMA phone if (TelephonyManager.PHONE_TYPE_CDMA != activePhoneType) { PreferenceScreen simLockPreferences = getPreferenceManager() .createPreferenceScreen(this); simLockPreferences.setTitle(R.string.sim_lock_settings_category); // Intent to launch SIM lock settings intent = new Intent(); intent.setClassName("com.android.settings", "com.android.settings.IccLockSettings"); simLockPreferences.setIntent(intent); PreferenceCategory simLockCat = new PreferenceCategory(this); simLockCat.setTitle(R.string.sim_lock_settings_title); root.addPreference(simLockCat); simLockCat.addPreference(simLockPreferences); } // Passwords PreferenceCategory passwordsCat = new PreferenceCategory(this); passwordsCat.setTitle(R.string.security_passwords_title); root.addPreference(passwordsCat); CheckBoxPreference showPassword = mShowPassword = new CheckBoxPreference(this); showPassword.setKey("show_password"); showPassword.setTitle(R.string.show_password); showPassword.setSummary(R.string.show_password_summary); showPassword.setPersistent(false); passwordsCat.addPreference(showPassword); // Credential storage PreferenceCategory credStoreCat = new PreferenceCategory(this); credStoreCat.setTitle(R.string.cstor_settings_category); root.addPreference(credStoreCat); credStoreCat.addPreference(mCstorHelper.createAccessCheckBox()); credStoreCat.addPreference(mCstorHelper.createCertInstallPreference()); credStoreCat.addPreference(mCstorHelper.createSetPasswordPreference()); credStoreCat.addPreference(mCstorHelper.createResetPreference()); return root; } @Override protected void onResume() { super.onResume(); boolean patternExists = mLockPatternUtils.savedPatternExists(); mLockEnabled.setEnabled(patternExists); mVisiblePattern.setEnabled(patternExists); mTactileFeedback.setEnabled(patternExists); mLockEnabled.setChecked(mLockPatternUtils.isLockPatternEnabled()); mVisiblePattern.setChecked(mLockPatternUtils.isVisiblePatternEnabled()); mTactileFeedback.setChecked(mLockPatternUtils.isTactileFeedbackEnabled()); int chooseStringRes = mLockPatternUtils.savedPatternExists() ? R.string.lockpattern_settings_change_lock_pattern : R.string.lockpattern_settings_choose_lock_pattern; mChoosePattern.setTitle(chooseStringRes); mShowPassword .setChecked(Settings.System.getInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD, 1) != 0); mCstorHelper.resumeStates(); } @Override public void onStop() { if (mUseLocationDialog != null && mUseLocationDialog.isShowing()) { mUseLocationDialog.dismiss(); } mUseLocationDialog = null; super.onStop(); } @Override public void onSaveInstanceState(Bundle icicle) { if (mUseLocationDialog != null && mUseLocationDialog.isShowing()) { icicle.putBoolean(KEY_DONE_USE_LOCATION, false); } super.onSaveInstanceState(icicle); } @Override public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { final String key = preference.getKey(); if (KEY_LOCK_ENABLED.equals(key)) { mLockPatternUtils.setLockPatternEnabled(isToggled(preference)); } else if (KEY_VISIBLE_PATTERN.equals(key)) { mLockPatternUtils.setVisiblePatternEnabled(isToggled(preference)); } else if (KEY_TACTILE_FEEDBACK_ENABLED.equals(key)) { mLockPatternUtils.setTactileFeedbackEnabled(isToggled(preference)); } else if (preference == mShowPassword) { Settings.System.putInt(getContentResolver(), Settings.System.TEXT_SHOW_PASSWORD, mShowPassword.isChecked() ? 1 : 0); } else if (preference == mNetwork) { Settings.Secure.setLocationProviderEnabled(getContentResolver(), LocationManager.NETWORK_PROVIDER, mNetwork.isChecked()); } else if (preference == mGps) { boolean enabled = mGps.isChecked(); Settings.Secure.setLocationProviderEnabled(getContentResolver(), LocationManager.GPS_PROVIDER, enabled); if (mAssistedGps != null) { mAssistedGps.setEnabled(enabled); } } else if (preference == mAssistedGps) { Settings.Secure.putInt(getContentResolver(), Settings.Secure.ASSISTED_GPS_ENABLED, mAssistedGps.isChecked() ? 1 : 0); } else if (preference == mUseLocation) { //normally called on the toggle click if (mUseLocation.isChecked()) { showUseLocationDialog(false); } else { updateUseLocation(); } } return false; } private void showPrivacyPolicy() { Intent intent = new Intent("android.settings.TERMS"); startActivity(intent); } private void showUseLocationDialog(boolean force) { // Show a warning to the user that location data will be shared mOkClicked = false; if (force) { mUseLocation.setChecked(true); } if (hasAgreedToUseLocation()) return; CharSequence msg = getResources().getText(R.string.use_location_warning_message); mUseLocationDialog = new AlertDialog.Builder(this).setMessage(msg) .setTitle(R.string.use_location_title) .setIcon(android.R.drawable.ic_dialog_alert) .setPositiveButton(R.string.agree, this) .setNegativeButton(R.string.disagree, this) .show(); ((TextView)mUseLocationDialog.findViewById(android.R.id.message)) .setMovementMethod(LinkMovementMethod.getInstance()); mUseLocationDialog.setOnDismissListener(this); } /* * Creates toggles for each available location provider */ private void updateToggles() { ContentResolver res = getContentResolver(); boolean gpsEnabled = Settings.Secure.isLocationProviderEnabled( res, LocationManager.GPS_PROVIDER); mNetwork.setChecked(Settings.Secure.isLocationProviderEnabled( res, LocationManager.NETWORK_PROVIDER)); mGps.setChecked(gpsEnabled); if (mAssistedGps != null) { mAssistedGps.setChecked(Settings.Secure.getInt(res, Settings.Secure.ASSISTED_GPS_ENABLED, 2) == 1); mAssistedGps.setEnabled(gpsEnabled); } mUseLocation.setChecked(Settings.Secure.getInt(res, Settings.Secure.USE_LOCATION_FOR_SERVICES, 2) == 1); } private boolean isToggled(Preference pref) { return ((CheckBoxPreference) pref).isChecked(); } private void updateUseLocation() { boolean use = mUseLocation.isChecked(); Settings.Secure.putInt(getContentResolver(), Settings.Secure.USE_LOCATION_FOR_SERVICES, use ? 1 : 0); } /** * For the user to disable keyguard, we first make them verify their * existing pattern. */ private class LockEnabledPref extends CheckBoxPreference { public LockEnabledPref(Context context) { super(context); } @Override protected void onClick() { if (mLockPatternUtils.savedPatternExists() && isChecked()) { confirmPatternThenDisableAndClear(); } else { super.onClick(); } } } /** * Launch screen to confirm the existing lock pattern. * @see #onActivityResult(int, int, android.content.Intent) */ private void confirmPatternThenDisableAndClear() { final Intent intent = new Intent(); intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern"); startActivityForResult(intent, CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE); } /** * @see #confirmPatternThenDisableAndClear */ @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); final boolean resultOk = resultCode == Activity.RESULT_OK; if ((requestCode == CONFIRM_PATTERN_THEN_DISABLE_AND_CLEAR_REQUEST_CODE) && resultOk) { mLockPatternUtils.setLockPatternEnabled(false); mLockPatternUtils.saveLockPattern(null); } } public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_POSITIVE) { //updateProviders(); mOkClicked = true; setAgreedToUseLocation(true); } else { // Reset the toggle mUseLocation.setChecked(false); } updateUseLocation(); } public void onDismiss(DialogInterface dialog) { // Assuming that onClick gets called first if (!mOkClicked) { mUseLocation.setChecked(false); } } @Override protected Dialog onCreateDialog (int id) { switch (id) { case CSTOR_INIT_DIALOG: case CSTOR_CHANGE_PASSWORD_DIALOG: return mCstorHelper.createSetPasswordDialog(id); case CSTOR_UNLOCK_DIALOG: return mCstorHelper.createUnlockDialog(); case CSTOR_RESET_DIALOG: return mCstorHelper.createResetDialog(); case CSTOR_NAME_CREDENTIAL_DIALOG: return mCstorHelper.createNameCredentialDialog(); default: return null; } } private boolean hasAgreedToUseLocation() { SharedPreferences sp = getSharedPreferences(PREFS_NAME, 0); if (sp == null) { return false; } return sp.getBoolean(PREFS_USE_LOCATION, false); } private void setAgreedToUseLocation(boolean agreed) { if (agreed) { SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(PREFS_USE_LOCATION, true); editor.commit(); } } private class CstorHelper implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener, DialogInterface.OnCancelListener { private Keystore mKeystore = Keystore.getInstance(); private View mView; private int mDialogId; private boolean mConfirm = true; private CheckBoxPreference mAccessCheckBox; private Preference mResetButton; private Intent mSpecialIntent; private CstorAddCredentialHelper mCstorAddCredentialHelper; void handleCstorIntents(Intent intent) { if (intent == null) return; String action = intent.getAction(); if (CertTool.ACTION_ADD_CREDENTIAL.equals(action)) { mCstorAddCredentialHelper = new CstorAddCredentialHelper(intent); showCstorDialog(CSTOR_NAME_CREDENTIAL_DIALOG); } else if (Keystore.ACTION_UNLOCK_CREDENTIAL_STORAGE.equals( action)) { mSpecialIntent = intent; showCstorDialog(mCstorHelper.isCstorInitialized() ? CSTOR_UNLOCK_DIALOG : CSTOR_INIT_DIALOG); } } void resumeStates() { int state = mCstorHelper.getCstorState(); mAccessCheckBox.setEnabled(state != Keystore.UNINITIALIZED); mAccessCheckBox.setChecked(state == Keystore.UNLOCKED); mResetButton.setEnabled(state != Keystore.UNINITIALIZED); } private void showCstorDialog(int dialogId) { mDialogId = dialogId; showDialog(dialogId); if (dialogId == CSTOR_NAME_CREDENTIAL_DIALOG) { // set mView back as mView may be replaced by CSTOR_INIT_DIALOG // or CSTOR_UNLOCK_DIALOG mView = mCstorAddCredentialHelper.mView; } } private int getCstorState() { return mKeystore.getState(); } private boolean isCstorUnlocked() { return (mKeystore.getState() == Keystore.UNLOCKED); } private boolean isCstorInitialized() { return (mKeystore.getState() != Keystore.UNINITIALIZED); } private void lockCstor() { mKeystore.lock(); mAccessCheckBox.setChecked(false); } private int unlockCstor(String passwd) { int ret = mKeystore.unlock(passwd); if (ret == -1) resetCstor(); if (ret == 0) { Toast.makeText(SecuritySettings.this, R.string.cstor_is_enabled, Toast.LENGTH_SHORT).show(); } return ret; } private int changeCstorPassword(String oldPasswd, String newPasswd) { int ret = mKeystore.changePassword(oldPasswd, newPasswd); if (ret == -1) resetCstor(); return ret; } private void initCstor(String passwd) { mKeystore.setPassword(passwd); enablePreferences(true); mAccessCheckBox.setChecked(true); Toast.makeText(SecuritySettings.this, R.string.cstor_is_enabled, Toast.LENGTH_SHORT).show(); } private void resetCstor() { mKeystore.reset(); enablePreferences(false); mAccessCheckBox.setChecked(false); Toast.makeText(SecuritySettings.this, R.string.cstor_is_reset, Toast.LENGTH_LONG).show(); } private boolean addCredential() { if (mCstorAddCredentialHelper.saveToStorage() != 0) { // set mView back as mView may be replaced by CSTOR_INIT_DIALOG // or CSTOR_UNLOCK_DIALOG mView = mCstorAddCredentialHelper.mView; if (mCstorAddCredentialHelper.isPkcs12Keystore()) { showError(R.string.cstor_password_error); } else { showError(R.string.cstor_storage_error); } Log.d("CSTOR", "failed to add credential"); return false; } Log.d("CSTOR", "credential is added: " + mCstorAddCredentialHelper.getName()); String formatString = getString(R.string.cstor_is_added); String message = String.format(formatString, mCstorAddCredentialHelper.getName()); Toast.makeText(SecuritySettings.this, message, Toast.LENGTH_LONG).show(); return true; } public void onCancel(DialogInterface dialog) { if (mCstorAddCredentialHelper == null) return; switch (mDialogId) { case CSTOR_INIT_DIALOG: case CSTOR_UNLOCK_DIALOG: Toast.makeText(SecuritySettings.this, R.string.cstor_unable_to_save_cert, Toast.LENGTH_LONG).show(); break; case CSTOR_NAME_CREDENTIAL_DIALOG: Toast.makeText(SecuritySettings.this, R.string.cstor_cert_not_saved, Toast.LENGTH_LONG).show(); break; } mCstorAddCredentialHelper = null; finish(); } public void onClick(DialogInterface dialog, int which) { if (which == DialogInterface.BUTTON_NEGATIVE) { onCancel(dialog); return; } switch (mDialogId) { case CSTOR_INIT_DIALOG: case CSTOR_CHANGE_PASSWORD_DIALOG: mConfirm = checkPasswords((Dialog) dialog); break; case CSTOR_UNLOCK_DIALOG: mConfirm = checkUnlockPassword((Dialog) dialog); break; case CSTOR_RESET_DIALOG: resetCstor(); break; case CSTOR_NAME_CREDENTIAL_DIALOG: mConfirm = checkAddCredential(); break; } } public void onDismiss(DialogInterface dialog) { if (!mConfirm) { mConfirm = true; showCstorDialog(mDialogId); } else { if (mDialogId == CSTOR_UNLOCK_DIALOG) { mAccessCheckBox.setChecked(isCstorUnlocked()); } if (mCstorAddCredentialHelper != null) { if (!isCstorInitialized()) { showCstorDialog(CSTOR_INIT_DIALOG); } else if (!isCstorUnlocked()) { showCstorDialog(CSTOR_UNLOCK_DIALOG); } else { if (addCredential()) { // succeeded finish(); } else { // failed if (mDialogId != CSTOR_NAME_CREDENTIAL_DIALOG) { removeDialog(mDialogId); } showCstorDialog(CSTOR_NAME_CREDENTIAL_DIALOG); } } return; } else if (mSpecialIntent != null) { finish(); } removeDialog(mDialogId); } } private void showResetWarning(int count) { TextView v = showError(count <= 3 ? R.string.cstor_password_error_reset_warning : R.string.cstor_password_error); if (count <= 3) { if (count == 1) { v.setText(R.string.cstor_password_error_reset_warning); } else { String format = getString( R.string.cstor_password_error_reset_warning_plural); v.setText(String.format(format, count)); } } } private boolean checkAddCredential() { hideError(); String name = getText(R.id.cstor_credential_name); if (TextUtils.isEmpty(name)) { showError(R.string.cstor_name_empty_error); return false; } for (int i = 0, len = name.length(); i < len; i++) { if (!Character.isLetterOrDigit(name.charAt(i))) { showError(R.string.cstor_name_char_error); return false; } } mCstorAddCredentialHelper.setName(name); if (mCstorAddCredentialHelper.isPkcs12Keystore()) { String password = getText(R.id.cstor_credential_password); if (TextUtils.isEmpty(password)) { showError(R.string.cstor_password_empty_error); return false; } mCstorAddCredentialHelper.setPassword(password); } return true; } // returns true if the password is long enough and does not contain // characters that we don't like private boolean verifyPassword(String passwd) { if (passwd == null) { showError(R.string.cstor_passwords_empty_error); return false; } else if (passwd.length() < CSTOR_MIN_PASSWORD_LENGTH) { showError(R.string.cstor_password_verification_error); return false; } else { return true; } } // returns true if the password is ok private boolean checkUnlockPassword(Dialog d) { hideError(); String passwd = getText(R.id.cstor_password); if (TextUtils.isEmpty(passwd)) { showError(R.string.cstor_password_empty_error); return false; } int count = unlockCstor(passwd); if (count > 0) { showResetWarning(count); return false; } else { // done or reset return true; } } // returns true if the passwords are ok private boolean checkPasswords(Dialog d) { hideError(); String oldPasswd = getText(R.id.cstor_old_password); String newPasswd = getText(R.id.cstor_new_password); String confirmPasswd = getText(R.id.cstor_confirm_password); if ((mDialogId == CSTOR_CHANGE_PASSWORD_DIALOG) && TextUtils.isEmpty(oldPasswd)) { showError(R.string.cstor_password_empty_error); return false; } if (TextUtils.isEmpty(newPasswd) && TextUtils.isEmpty(confirmPasswd)) { showError(R.string.cstor_passwords_empty_error); return false; } if (!verifyPassword(newPasswd)) { return false; } else if (!newPasswd.equals(confirmPasswd)) { showError(R.string.cstor_passwords_error); return false; } if (mDialogId == CSTOR_CHANGE_PASSWORD_DIALOG) { int count = changeCstorPassword(oldPasswd, newPasswd); if (count > 0) { showResetWarning(count); return false; } else { // done or reset return true; } } else { initCstor(newPasswd); return true; } } private void installCertFromSdCard() { startActivity(new Intent(CertTool.ACTION_INSTALL_CERT_FROM_SDCARD)); } private TextView showError(int messageId) { TextView v = (TextView) mView.findViewById(R.id.cstor_error); v.setText(messageId); if (v != null) v.setVisibility(View.VISIBLE); return v; } private void hide(int viewId) { View v = mView.findViewById(viewId); if (v != null) v.setVisibility(View.GONE); } private void hideError() { hide(R.id.cstor_error); } private String getText(int viewId) { return ((TextView) mView.findViewById(viewId)).getText().toString(); } private void setText(int viewId, String text) { TextView v = (TextView) mView.findViewById(viewId); if (v != null) v.setText(text); } private void setText(int viewId, int textId) { TextView v = (TextView) mView.findViewById(viewId); if (v != null) v.setText(textId); } private void enablePreferences(boolean enabled) { mAccessCheckBox.setEnabled(enabled); mResetButton.setEnabled(enabled); } private Preference createAccessCheckBox() { CheckBoxPreference pref = new CheckBoxPreference( SecuritySettings.this); pref.setTitle(R.string.cstor_access_title); pref.setSummary(R.string.cstor_access_summary); pref.setOnPreferenceChangeListener( new Preference.OnPreferenceChangeListener() { public boolean onPreferenceChange( Preference pref, Object value) { if (((Boolean) value)) { showCstorDialog(CSTOR_UNLOCK_DIALOG); } else { lockCstor(); } return true; } }); mAccessCheckBox = pref; return pref; } private Preference createCertInstallPreference() { Preference pref = new Preference(SecuritySettings.this); pref.setTitle(R.string.cstor_cert_install_title); pref.setSummary(R.string.cstor_cert_install_summary); pref.setOnPreferenceClickListener( new Preference.OnPreferenceClickListener() { public boolean onPreferenceClick(Preference pref) { installCertFromSdCard(); return true; } }); return pref; } private Preference createSetPasswordPreference() { Preference pref = new Preference(SecuritySettings.this); pref.setTitle(R.string.cstor_set_passwd_title); pref.setSummary(R.string.cstor_set_passwd_summary); pref.setOnPreferenceClickListener( new Preference.OnPreferenceClickListener() { public boolean onPreferenceClick(Preference pref) { showCstorDialog(isCstorInitialized() ? CSTOR_CHANGE_PASSWORD_DIALOG : CSTOR_INIT_DIALOG); return true; } }); return pref; } private Preference createResetPreference() { Preference pref = new Preference(SecuritySettings.this); pref.setTitle(R.string.cstor_reset_title); pref.setSummary(R.string.cstor_reset_summary); pref.setOnPreferenceClickListener( new Preference.OnPreferenceClickListener() { public boolean onPreferenceClick(Preference pref) { showCstorDialog(CSTOR_RESET_DIALOG); return true; } }); mResetButton = pref; return pref; } private Dialog createUnlockDialog() { mView = View.inflate(SecuritySettings.this, R.layout.cstor_unlock_dialog_view, null); hideError(); // show extra hint only when the action comes from outside if ((mSpecialIntent == null) && (mCstorAddCredentialHelper == null)) { hide(R.id.cstor_access_dialog_hint_from_action); } Dialog d = new AlertDialog.Builder(SecuritySettings.this) .setView(mView) .setTitle(R.string.cstor_access_dialog_title) .setPositiveButton(android.R.string.ok, this) .setNegativeButton(android.R.string.cancel, this) .setOnCancelListener(this) .create(); d.setOnDismissListener(this); return d; } private Dialog createSetPasswordDialog(int id) { mView = View.inflate(SecuritySettings.this, R.layout.cstor_set_password_dialog_view, null); hideError(); // show extra hint only when the action comes from outside if ((mSpecialIntent != null) || (mCstorAddCredentialHelper != null)) { setText(R.id.cstor_first_time_hint, R.string.cstor_first_time_hint_from_action); } switch (id) { case CSTOR_INIT_DIALOG: mView.findViewById(R.id.cstor_old_password_block) .setVisibility(View.GONE); break; case CSTOR_CHANGE_PASSWORD_DIALOG: mView.findViewById(R.id.cstor_first_time_hint) .setVisibility(View.GONE); break; default: throw new RuntimeException( "Unknown dialog id: " + mDialogId); } Dialog d = new AlertDialog.Builder(SecuritySettings.this) .setView(mView) .setTitle(R.string.cstor_set_passwd_dialog_title) .setPositiveButton(android.R.string.ok, this) .setNegativeButton(android.R.string.cancel, this) .setOnCancelListener(this) .create(); d.setOnDismissListener(this); return d; } private Dialog createResetDialog() { return new AlertDialog.Builder(SecuritySettings.this) .setTitle(android.R.string.dialog_alert_title) .setIcon(android.R.drawable.ic_dialog_alert) .setMessage(R.string.cstor_reset_hint) .setPositiveButton(getString(android.R.string.ok), this) .setNegativeButton(getString(android.R.string.cancel), this) .create(); } private Dialog createNameCredentialDialog() { mView = View.inflate(SecuritySettings.this, R.layout.cstor_name_credential_dialog_view, null); if (mCstorAddCredentialHelper != null) { mCstorAddCredentialHelper.mView = mView; } hideError(); if (!mCstorAddCredentialHelper.isPkcs12Keystore()) { hide(R.id.cstor_credential_password_container); } setText(R.id.cstor_credential_name_title, R.string.cstor_credential_name); setText(R.id.cstor_credential_info_title, R.string.cstor_credential_info); setText(R.id.cstor_credential_info, mCstorAddCredentialHelper.getDescription().toString()); Dialog d = new AlertDialog.Builder(SecuritySettings.this) .setView(mView) .setTitle(R.string.cstor_name_credential_dialog_title) .setPositiveButton(android.R.string.ok, this) .setNegativeButton(android.R.string.cancel, this) .setOnCancelListener(this) .create(); d.setOnDismissListener(this); return d; } } private class CstorAddCredentialHelper { private String mTypeName; private List mItemList; private List mNamespaceList; private String mDescription; private String mName; private String mPassword; private View mView; CstorAddCredentialHelper(Intent intent) { parse(intent); } String getTypeName() { return mTypeName; } boolean isPkcs12Keystore() { return CertTool.TITLE_PKCS12_KEYSTORE.equals(mTypeName); } CharSequence getDescription() { return Html.fromHtml(mDescription); } void setName(String name) { mName = name; } String getName() { return mName; } void setPassword(String password) { mPassword = password; } String getPassword() { return mPassword; } int saveToStorage() { if (isPkcs12Keystore()) { return CertTool.getInstance().addPkcs12Keystore( mItemList.get(0), mPassword, mName); } else { Keystore ks = Keystore.getInstance(); for (int i = 0, count = mItemList.size(); i < count; i++) { byte[] blob = mItemList.get(i); int ret = ks.put(mNamespaceList.get(i), mName, new String(blob)); if (ret != 0) return ret; } } return 0; } private void parse(Intent intent) { mTypeName = intent.getStringExtra(KEY_CSTOR_TYPE_NAME); mItemList = new ArrayList(); mNamespaceList = new ArrayList(); for (int i = 0; ; i++) { byte[] blob = intent.getByteArrayExtra(KEY_CSTOR_ITEM + i); if (blob == null) break; mItemList.add(blob); mNamespaceList.add(intent.getStringExtra( KEY_CSTOR_NAMESPACE + i)); } // build description string StringBuilder sb = new StringBuilder(); for (int i = 0; ; i++) { String s = intent.getStringExtra(KEY_CSTOR_DESCRIPTION + i); if (s == null) break; sb.append(s).append("
"); } mDescription = sb.toString(); } } }