summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xAndroidManifest.xml38
-rwxr-xr-xres/values/config.xml2
-rw-r--r--res/values/strings.xml15
-rw-r--r--res/xml/anonymous_stats.xml32
-rw-r--r--res/xml/preview_data.xml53
-rw-r--r--res/xml/privacy_settings_cyanogenmod.xml19
-rw-r--r--res/xml/security_settings_encrypted.xml22
-rw-r--r--src/com/android/settings/ChooseEncryptionPassword.java682
-rw-r--r--src/com/android/settings/DevelopmentSettings.java2
-rw-r--r--src/com/android/settings/ReplaceEncryptionPassword.java105
-rw-r--r--src/com/android/settings/SecuritySettings.java11
-rw-r--r--src/com/android/settings/Settings.java1
-rw-r--r--src/com/android/settings/SettingsActivity.java4
-rw-r--r--src/com/android/settings/cmstats/AnonymousStats.java81
-rw-r--r--src/com/android/settings/cmstats/PreviewData.java55
-rw-r--r--src/com/android/settings/cmstats/ReportingService.java82
-rw-r--r--src/com/android/settings/cmstats/ReportingServiceManager.java109
-rw-r--r--src/com/android/settings/cmstats/StatsUploadJobService.java205
-rw-r--r--src/com/android/settings/cmstats/Utilities.java102
19 files changed, 841 insertions, 779 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index ffeb655..0ff184b 100755
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1556,18 +1556,17 @@
<activity android:name="ChooseLockPassword" android:exported="false"
android:windowSoftInputMode="stateVisible|adjustResize"/>
+ <activity android:name="ChooseEncryptionPassword" android:exported="false"
+ android:windowSoftInputMode="stateVisible|adjustResize"/>
+
+ <activity android:name="ReplaceEncryptionPassword" android:exported="false"/>
+
<activity android:name=".SetupEncryptionInterstitial"
android:taskAffinity="com.android.wizard"
android:theme="@style/SetupWizardDisableAppStartingTheme"/>
<activity android:name=".EncryptionInterstitial"/>
- <service android:label="ReportingService"
- android:enabled="true"
- android:exported="false"
- android:name=".cmstats.ReportingService">
- </service>
-
<!-- Runs in the phone process since it needs access to the Phone object -->
<activity android:name=".deviceinfo.Status"
android:label="@string/device_status_activity_title"
@@ -1943,13 +1942,6 @@
<!-- Development settings -->
- <!-- DeviceInfo adds the user's requested build to stats upload. -->
- <receiver android:name=".DeviceInfo$StatsReportReceiver">
- <intent-filter>
- <action android:name="android.intent.action.STATISTICS_REPORT" />
- </intent-filter>
- </receiver>
-
<activity android:name="Display" android:label="@string/display_label"
android:configChanges="fontScale"
android:taskAffinity="com.android.settings"
@@ -2691,26 +2683,6 @@
</intent-filter>$
</receiver>
- <!-- Anonymous Statistics -->
- <receiver android:name=".cmstats.ReportingServiceManager"
- android:enabled="true"
- android:exported="false"
- android:label="ReportingServiceManager">
- <intent-filter>
- <action android:name="android.intent.action.BOOT_COMPLETED" />
- <action android:name="com.android.settings.action.TRIGGER_REPORT_METRICS" />
- </intent-filter>
- </receiver>
-
- <service android:label="ReportingService"
- android:enabled="true"
- android:exported="false"
- android:name=".cmstats.ReportingService">
- </service>
-
- <service android:name=".cmstats.StatsUploadJobService"
- android:permission="android.permission.BIND_JOB_SERVICE" />
-
<!-- Watch for ContactsContract.Profile changes and update the user's photo. -->
<receiver android:name=".users.ProfileUpdateReceiver">
<intent-filter>
diff --git a/res/values/config.xml b/res/values/config.xml
index b7ccf9b..32d81ab 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -51,8 +51,6 @@
<!-- Config to enable duplicate APN checking. When true, disallows adding new duplicate APNs -->
<bool name="config_enable_duplicate_apn_checking">false</bool>
- <!-- Metrics server endpoint -->
- <string name="stats_cm_url">https://stats.lineageos.org/api/v1/stats</string>
<!-- Display ro.product.name above Device model -->
<bool name="config_displayDeviceName">false</bool>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 6a5d5d8..e5efde6 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -937,6 +937,21 @@
<!-- Image button description to switch input method -->
<string name="crypt_keeper_switch_input_method">Switch input method</string>
+ <!-- Title for PreferenceScreen to change encryption password [CHAR LIMIT=22] -->
+ <string name="crypt_keeper_change_password_title">Change encryption password</string>
+
+ <!-- Summary for PreferenceScreen to change encryption password [CHAR LIMIT=45] -->
+ <string name="crypt_keeper_change_password_summary">Change the password used for device encryption</string>
+
+ <!-- Header on first screen of choose encryption password [CHAR LIMIT=30] -->
+ <string name="crypt_keeper_choose_your_password_header">Set encryption password</string>
+
+ <!-- Title for PreferenceScreen to replace encryption password [CHAR LIMIT=22] -->
+ <string name="crypt_keeper_replace_password_title">Replace encryption password</string>
+
+ <!-- Summary for PreferenceScreen to replace encryption password [CHAR LIMIT=45] -->
+ <string name="crypt_keeper_replace_password_summary">Remove the separate encryption password</string>
+
<!-- Unlock Picker Settings --><skip />
<!-- Security Picker --><skip />
diff --git a/res/xml/anonymous_stats.xml b/res/xml/anonymous_stats.xml
deleted file mode 100644
index 0f3b8e2..0000000
--- a/res/xml/anonymous_stats.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The CyanogenMod 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.
--->
-
-<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="@string/anonymous_statistics_title"
- xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
-
- <com.android.settings.cyanogenmod.CMSecureSettingSwitchPreference
- android:key="stats_collection"
- android:title="@string/stats_collection_title"
- android:summary="@string/stats_collection_summary"
- android:defaultValue="true" />
-
- <PreferenceScreen
- android:title="@string/preview_data_title"
- android:fragment="com.android.settings.cmstats.PreviewData" />
-
-</PreferenceScreen>
diff --git a/res/xml/preview_data.xml b/res/xml/preview_data.xml
deleted file mode 100644
index 966e501..0000000
--- a/res/xml/preview_data.xml
+++ /dev/null
@@ -1,53 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The CyanogenMod 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.
--->
-
-<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:title="@string/preview_data_title"
- xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
-
- <Preference
- android:key="preview_id"
- style="?android:preferenceInformationStyle"
- android:title="@string/preview_id_title"
- android:summary="%s" />
-
- <Preference
- android:key="preview_device"
- style="?android:preferenceInformationStyle"
- android:title="@string/preview_device_title"
- android:summary="%s" />
-
- <Preference
- android:key="preview_version"
- style="?android:preferenceInformationStyle"
- android:title="@string/preview_version_title"
- android:summary="%s" />
-
- <Preference
- android:key="preview_country"
- style="?android:preferenceInformationStyle"
- android:title="@string/preview_country_title"
- android:summary="%s" />
-
- <Preference
- android:key="preview_carrier"
- style="?android:preferenceInformationStyle"
- android:title="@string/preview_carrier_title"
- android:summary="%s" />
-
-</PreferenceScreen>
-
diff --git a/res/xml/privacy_settings_cyanogenmod.xml b/res/xml/privacy_settings_cyanogenmod.xml
index 1ce0f12..cf84b02 100644
--- a/res/xml/privacy_settings_cyanogenmod.xml
+++ b/res/xml/privacy_settings_cyanogenmod.xml
@@ -28,23 +28,4 @@
android:title="@string/blacklist_title"
android:summary="@string/blacklist_summary"
android:fragment="com.android.settings.blacklist.BlacklistSettings" />
-
- <!-- Anonymous statistics - (CMStats) -->
- <PreferenceScreen
- android:key="cmstats"
- android:title="@string/anonymous_statistics_title"
- android:summary="@string/anonymous_statistics_summary"
- android:fragment="com.android.settings.cmstats.AnonymousStats" >
- </PreferenceScreen>
-
- <!-- Protected Apps! -->
- <Preference
- android:key="protected_apps_manager"
- android:title="@string/protected_apps"
- android:summary="@string/protected_apps_summary">
- <intent
- android:action="android.intent.action.VIEW"
- android:targetPackage="com.android.settings"
- android:targetClass="com.android.settings.applications.ProtectedAppsActivity" />
- </Preference>
</PreferenceScreen>
diff --git a/res/xml/security_settings_encrypted.xml b/res/xml/security_settings_encrypted.xml
index 2399243..4a54788 100644
--- a/res/xml/security_settings_encrypted.xml
+++ b/res/xml/security_settings_encrypted.xml
@@ -18,7 +18,7 @@
android:title="@string/security_settings_title">
<PreferenceCategory
- android:key="security_category"
+ android:key="encryption_category"
android:title="@string/crypt_keeper_settings_title">
<Preference
@@ -27,6 +27,26 @@
android:title="@string/crypt_keeper_encrypt_title"
android:summary="@string/crypt_keeper_encrypted_summary"/>
+ <Preference
+ android:key="crypt_keeper_change_password"
+ android:title="@string/crypt_keeper_change_password_title"
+ android:summary="@string/crypt_keeper_change_password_summary">
+
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.ChooseEncryptionPassword" />
+ </Preference>
+
+ <Preference
+ android:key="crypt_keeper_replace_password"
+ android:title="@string/crypt_keeper_replace_password_title"
+ android:summary="@string/crypt_keeper_replace_password_summary">
+
+ <intent android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.ReplaceEncryptionPassword" />
+ </Preference>
+
</PreferenceCategory>
diff --git a/src/com/android/settings/ChooseEncryptionPassword.java b/src/com/android/settings/ChooseEncryptionPassword.java
new file mode 100644
index 0000000..43e2b0e
--- /dev/null
+++ b/src/com/android/settings/ChooseEncryptionPassword.java
@@ -0,0 +1,682 @@
+/*
+ * Copyright (C) 2015 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 com.android.internal.logging.MetricsLogger;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.PasswordEntryKeyboardHelper;
+import com.android.internal.widget.PasswordEntryKeyboardView;
+import com.android.internal.widget.TextViewInputDisabler;
+import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
+import com.android.settings.notification.RedactionInterstitial;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.admin.DevicePolicyManager;
+import android.content.Context;
+import android.content.Intent;
+import android.inputmethodservice.KeyboardView;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.UserHandle;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.Selection;
+import android.text.Spannable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+public class ChooseEncryptionPassword extends SettingsActivity {
+ public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
+ public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
+ public static final String PASSWORD_MIN_LETTERS_KEY = "lockscreen.password_min_letters";
+ public static final String PASSWORD_MIN_LOWERCASE_KEY = "lockscreen.password_min_lowercase";
+ public static final String PASSWORD_MIN_UPPERCASE_KEY = "lockscreen.password_min_uppercase";
+ public static final String PASSWORD_MIN_NUMERIC_KEY = "lockscreen.password_min_numeric";
+ public static final String PASSWORD_MIN_SYMBOLS_KEY = "lockscreen.password_min_symbols";
+ public static final String PASSWORD_MIN_NONLETTER_KEY = "lockscreen.password_min_nonletter";
+
+ private static final String TAG = "ChooseEncryptionPassword";
+
+ @Override
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName());
+ return modIntent;
+ }
+
+ public static Intent createIntent(Context context, int quality,
+ int minLength, final int maxLength, boolean requirePasswordToDecrypt,
+ boolean confirmCredentials) {
+ Intent intent = new Intent().setClass(context, ChooseEncryptionPassword.class);
+ intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality);
+ intent.putExtra(PASSWORD_MIN_KEY, minLength);
+ intent.putExtra(PASSWORD_MAX_KEY, maxLength);
+ intent.putExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, confirmCredentials);
+ intent.putExtra(EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, requirePasswordToDecrypt);
+ return intent;
+ }
+
+ public static Intent createIntent(Context context, int quality,
+ int minLength, final int maxLength, boolean requirePasswordToDecrypt, String password) {
+ Intent intent = createIntent(context, quality, minLength, maxLength,
+ requirePasswordToDecrypt, false);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD, password);
+ return intent;
+ }
+
+ public static Intent createIntent(Context context, int quality,
+ int minLength, final int maxLength, boolean requirePasswordToDecrypt, long challenge) {
+ Intent intent = createIntent(context, quality, minLength, maxLength,
+ requirePasswordToDecrypt, false);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, true);
+ intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, challenge);
+ return intent;
+ }
+
+ @Override
+ protected boolean isValidFragment(String fragmentName) {
+ if (ChooseEncryptionPasswordFragment.class.getName().equals(fragmentName)) return true;
+ return false;
+ }
+
+ /* package */ Class<? extends Fragment> getFragmentClass() {
+ return ChooseEncryptionPasswordFragment.class;
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ // TODO: Fix on phones
+ // Disable IME on our window since we provide our own keyboard
+ //getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
+ //WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
+ super.onCreate(savedInstanceState);
+ CharSequence msg = getText(R.string.lockpassword_choose_your_password_header);
+ setTitle(msg);
+ }
+
+ public static class ChooseEncryptionPasswordFragment extends InstrumentedFragment
+ implements OnClickListener, OnEditorActionListener, TextWatcher,
+ SaveAndFinishWorker.Listener {
+ private static final String KEY_FIRST_PIN = "first_pin";
+ private static final String KEY_UI_STAGE = "ui_stage";
+ private static final String KEY_CURRENT_PASSWORD = "current_password";
+ private static final String FRAGMENT_TAG_SAVE_AND_FINISH = "save_and_finish_worker";
+
+ private String mCurrentPassword;
+ private String mChosenPassword;
+ private boolean mHasChallenge;
+ private long mChallenge;
+ private TextView mPasswordEntry;
+ private TextViewInputDisabler mPasswordEntryInputDisabler;
+ private int mPasswordMinLength = LockPatternUtils.MIN_LOCK_PASSWORD_SIZE;
+ private int mPasswordMaxLength = 16;
+ private int mPasswordMinLetters = 0;
+ private int mPasswordMinUpperCase = 0;
+ private int mPasswordMinLowerCase = 0;
+ private int mPasswordMinSymbols = 0;
+ private int mPasswordMinNumeric = 0;
+ private int mPasswordMinNonLetter = 0;
+ private LockPatternUtils mLockPatternUtils;
+ private SaveAndFinishWorker mSaveAndFinishWorker;
+ private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
+ private ChooseLockSettingsHelper mChooseLockSettingsHelper;
+ private Stage mUiStage = Stage.Introduction;
+
+ private TextView mHeaderText;
+ private String mFirstPin;
+ private KeyboardView mKeyboardView;
+ private PasswordEntryKeyboardHelper mKeyboardHelper;
+ private boolean mIsAlphaMode;
+ private Button mCancelButton;
+ private Button mNextButton;
+ private static final int CONFIRM_EXISTING_REQUEST = 58;
+ static final int RESULT_FINISHED = RESULT_FIRST_USER;
+ private static final long ERROR_MESSAGE_TIMEOUT = 3000;
+ private static final int MSG_SHOW_ERROR = 1;
+
+ private Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_SHOW_ERROR) {
+ updateStage((Stage) msg.obj);
+ }
+ }
+ };
+
+ /**
+ * Keep track internally of where the user is in choosing a pattern.
+ */
+ protected enum Stage {
+
+ Introduction(R.string.lockpassword_choose_your_password_header,
+ R.string.lockpassword_choose_your_pin_header,
+ R.string.lockpassword_continue_label),
+
+ NeedToConfirm(R.string.lockpassword_confirm_your_password_header,
+ R.string.lockpassword_confirm_your_pin_header,
+ R.string.lockpassword_ok_label),
+
+ ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match,
+ R.string.lockpassword_confirm_pins_dont_match,
+ R.string.lockpassword_continue_label);
+
+ Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) {
+ this.alphaHint = hintInAlpha;
+ this.numericHint = hintInNumeric;
+ this.buttonText = nextButtonText;
+ }
+
+ public final int alphaHint;
+ public final int numericHint;
+ public final int buttonText;
+ }
+
+ // required constructor for fragments
+ public ChooseEncryptionPasswordFragment() {
+
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ mLockPatternUtils = new LockPatternUtils(getActivity());
+ Intent intent = getActivity().getIntent();
+ if (!(getActivity() instanceof ChooseEncryptionPassword)) {
+ throw new SecurityException("Fragment contained in wrong activity");
+ }
+ mRequestedQuality = Math.max(intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY,
+ mRequestedQuality), mLockPatternUtils.getRequestedPasswordQuality(
+ UserHandle.myUserId()));
+ mPasswordMinLength = Math.max(Math.max(
+ LockPatternUtils.MIN_LOCK_PASSWORD_SIZE,
+ intent.getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength)),
+ mLockPatternUtils.getRequestedMinimumPasswordLength(UserHandle.myUserId()));
+ mPasswordMaxLength = intent.getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);
+ mPasswordMinLetters = Math.max(intent.getIntExtra(PASSWORD_MIN_LETTERS_KEY,
+ mPasswordMinLetters), mLockPatternUtils.getRequestedPasswordMinimumLetters(
+ UserHandle.myUserId()));
+ mPasswordMinUpperCase = Math.max(intent.getIntExtra(PASSWORD_MIN_UPPERCASE_KEY,
+ mPasswordMinUpperCase), mLockPatternUtils.getRequestedPasswordMinimumUpperCase(
+ UserHandle.myUserId()));
+ mPasswordMinLowerCase = Math.max(intent.getIntExtra(PASSWORD_MIN_LOWERCASE_KEY,
+ mPasswordMinLowerCase), mLockPatternUtils.getRequestedPasswordMinimumLowerCase(
+ UserHandle.myUserId()));
+ mPasswordMinNumeric = Math.max(intent.getIntExtra(PASSWORD_MIN_NUMERIC_KEY,
+ mPasswordMinNumeric), mLockPatternUtils.getRequestedPasswordMinimumNumeric(
+ UserHandle.myUserId()));
+ mPasswordMinSymbols = Math.max(intent.getIntExtra(PASSWORD_MIN_SYMBOLS_KEY,
+ mPasswordMinSymbols), mLockPatternUtils.getRequestedPasswordMinimumSymbols(
+ UserHandle.myUserId()));
+ mPasswordMinNonLetter = Math.max(intent.getIntExtra(PASSWORD_MIN_NONLETTER_KEY,
+ mPasswordMinNonLetter), mLockPatternUtils.getRequestedPasswordMinimumNonLetter(
+ UserHandle.myUserId()));
+
+ mChooseLockSettingsHelper = new ChooseLockSettingsHelper(getActivity());
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ return inflater.inflate(R.layout.choose_lock_password, container, false);
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+
+ mCancelButton = (Button) view.findViewById(R.id.cancel_button);
+ mCancelButton.setOnClickListener(this);
+ mNextButton = (Button) view.findViewById(R.id.next_button);
+ mNextButton.setOnClickListener(this);
+
+ mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
+ || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality
+ || DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality;
+ mKeyboardView = (PasswordEntryKeyboardView) view.findViewById(R.id.keyboard);
+ mPasswordEntry = (TextView) view.findViewById(R.id.password_entry);
+ mPasswordEntry.setOnEditorActionListener(this);
+ mPasswordEntry.addTextChangedListener(this);
+ mPasswordEntryInputDisabler = new TextViewInputDisabler(mPasswordEntry);
+
+ final Activity activity = getActivity();
+ mKeyboardHelper = new PasswordEntryKeyboardHelper(activity,
+ mKeyboardView, mPasswordEntry);
+ mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
+ PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
+ : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
+
+ mHeaderText = (TextView) view.findViewById(R.id.headerText);
+ mKeyboardView.requestFocus();
+
+ int currentType = mPasswordEntry.getInputType();
+ mPasswordEntry.setInputType(mIsAlphaMode ? currentType
+ : (InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_PASSWORD));
+
+ Intent intent = getActivity().getIntent();
+ final boolean confirmCredentials = intent.getBooleanExtra(
+ ChooseLockGeneric.CONFIRM_CREDENTIALS, true);
+ mCurrentPassword = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
+ mHasChallenge = intent.getBooleanExtra(
+ ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
+ mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
+ if (savedInstanceState == null) {
+ updateStage(Stage.Introduction);
+ if (confirmCredentials) {
+ mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
+ getString(R.string.unlock_set_unlock_launch_picker_title), true);
+ }
+ } else {
+ // restore from previous state
+ mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
+ final String state = savedInstanceState.getString(KEY_UI_STAGE);
+ if (state != null) {
+ mUiStage = Stage.valueOf(state);
+ updateStage(mUiStage);
+ }
+
+ if (mCurrentPassword == null) {
+ mCurrentPassword = savedInstanceState.getString(KEY_CURRENT_PASSWORD);
+ }
+
+ // Re-attach to the exiting worker if there is one.
+ mSaveAndFinishWorker = (SaveAndFinishWorker) getFragmentManager().findFragmentByTag(
+ FRAGMENT_TAG_SAVE_AND_FINISH);
+ }
+ if (activity instanceof SettingsActivity) {
+ final SettingsActivity sa = (SettingsActivity) activity;
+ int id = mIsAlphaMode ? R.string.lockpassword_choose_your_password_header
+ : R.string.lockpassword_choose_your_pin_header;
+ CharSequence title = getText(id);
+ sa.setTitle(title);
+ }
+ }
+
+ @Override
+ protected int getMetricsCategory() {
+ return MetricsLogger.CHOOSE_LOCK_PASSWORD;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateStage(mUiStage);
+ if (mSaveAndFinishWorker != null) {
+ mSaveAndFinishWorker.setListener(this);
+ } else {
+ mKeyboardView.requestFocus();
+ }
+ }
+
+ @Override
+ public void onPause() {
+ mHandler.removeMessages(MSG_SHOW_ERROR);
+ if (mSaveAndFinishWorker != null) {
+ mSaveAndFinishWorker.setListener(null);
+ }
+
+ super.onPause();
+ }
+
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ outState.putString(KEY_UI_STAGE, mUiStage.name());
+ outState.putString(KEY_FIRST_PIN, mFirstPin);
+ outState.putString(KEY_CURRENT_PASSWORD, mCurrentPassword);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode,
+ Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ switch (requestCode) {
+ case CONFIRM_EXISTING_REQUEST:
+ if (resultCode != Activity.RESULT_OK) {
+ getActivity().setResult(RESULT_FINISHED);
+ getActivity().finish();
+ } else {
+ mCurrentPassword = data.getStringExtra(
+ ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
+ }
+ break;
+ }
+ }
+
+ protected Intent getRedactionInterstitialIntent(Context context) {
+ return RedactionInterstitial.createStartIntent(context);
+ }
+
+ protected void updateStage(Stage stage) {
+ final Stage previousStage = mUiStage;
+ mUiStage = stage;
+ updateUi();
+
+ // If the stage changed, announce the header for accessibility. This
+ // is a no-op when accessibility is disabled.
+ if (previousStage != stage) {
+ mHeaderText.announceForAccessibility(mHeaderText.getText());
+ }
+ }
+
+ /**
+ * Validates PIN and returns a message to display if PIN fails test.
+ * @param password the raw password the user typed in
+ * @return error message to show to user or null if password is OK
+ */
+ private String validatePassword(String password) {
+ if (password.length() < mPasswordMinLength) {
+ return getString(mIsAlphaMode ?
+ R.string.lockpassword_password_too_short
+ : R.string.lockpassword_pin_too_short, mPasswordMinLength);
+ }
+ if (password.length() > mPasswordMaxLength) {
+ return getString(mIsAlphaMode ?
+ R.string.lockpassword_password_too_long
+ : R.string.lockpassword_pin_too_long, mPasswordMaxLength + 1);
+ }
+ int letters = 0;
+ int numbers = 0;
+ int lowercase = 0;
+ int symbols = 0;
+ int uppercase = 0;
+ int nonletter = 0;
+ for (int i = 0; i < password.length(); i++) {
+ char c = password.charAt(i);
+ // allow non control Latin-1 characters only
+ if (c < 32 || c > 127) {
+ return getString(R.string.lockpassword_illegal_character);
+ }
+ if (c >= '0' && c <= '9') {
+ numbers++;
+ nonletter++;
+ } else if (c >= 'A' && c <= 'Z') {
+ letters++;
+ uppercase++;
+ } else if (c >= 'a' && c <= 'z') {
+ letters++;
+ lowercase++;
+ } else {
+ symbols++;
+ nonletter++;
+ }
+ }
+ if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
+ || DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX == mRequestedQuality) {
+ if (letters > 0 || symbols > 0) {
+ // This shouldn't be possible unless user finds some way to bring up
+ // soft keyboard
+ return getString(R.string.lockpassword_pin_contains_non_digits);
+ }
+ // Check for repeated characters or sequences (e.g. '1234', '0000', '2468')
+ final int sequence = LockPatternUtils.maxLengthSequence(password);
+ if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX == mRequestedQuality
+ && sequence > LockPatternUtils.MAX_ALLOWED_SEQUENCE) {
+ return getString(R.string.lockpassword_pin_no_sequential_digits);
+ }
+ } else if (DevicePolicyManager.PASSWORD_QUALITY_COMPLEX == mRequestedQuality) {
+ if (letters < mPasswordMinLetters) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_letters, mPasswordMinLetters),
+ mPasswordMinLetters);
+ } else if (numbers < mPasswordMinNumeric) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_numeric, mPasswordMinNumeric),
+ mPasswordMinNumeric);
+ } else if (lowercase < mPasswordMinLowerCase) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_lowercase, mPasswordMinLowerCase),
+ mPasswordMinLowerCase);
+ } else if (uppercase < mPasswordMinUpperCase) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_uppercase, mPasswordMinUpperCase),
+ mPasswordMinUpperCase);
+ } else if (symbols < mPasswordMinSymbols) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_symbols, mPasswordMinSymbols),
+ mPasswordMinSymbols);
+ } else if (nonletter < mPasswordMinNonLetter) {
+ return String.format(getResources().getQuantityString(
+ R.plurals.lockpassword_password_requires_nonletter, mPasswordMinNonLetter),
+ mPasswordMinNonLetter);
+ }
+ } else {
+ final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
+ == mRequestedQuality;
+ final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
+ == mRequestedQuality;
+ if ((alphabetic || alphanumeric) && letters == 0) {
+ return getString(R.string.lockpassword_password_requires_alpha);
+ }
+ if (alphanumeric && numbers == 0) {
+ return getString(R.string.lockpassword_password_requires_digit);
+ }
+ }
+ if(mLockPatternUtils.checkPasswordHistory(password, UserHandle.myUserId())) {
+ return getString(mIsAlphaMode ? R.string.lockpassword_password_recently_used
+ : R.string.lockpassword_pin_recently_used);
+ }
+
+ return null;
+ }
+
+ public void handleNext() {
+ if (mSaveAndFinishWorker != null) return;
+ mChosenPassword = mPasswordEntry.getText().toString();
+ if (TextUtils.isEmpty(mChosenPassword)) {
+ return;
+ }
+ String errorMsg = null;
+ if (mUiStage == Stage.Introduction) {
+ errorMsg = validatePassword(mChosenPassword);
+ if (errorMsg == null) {
+ mFirstPin = mChosenPassword;
+ mPasswordEntry.setText("");
+ updateStage(Stage.NeedToConfirm);
+ }
+ } else if (mUiStage == Stage.NeedToConfirm) {
+ if (mFirstPin.equals(mChosenPassword)) {
+ startSaveAndFinish();
+ } else {
+ CharSequence tmp = mPasswordEntry.getText();
+ if (tmp != null) {
+ Selection.setSelection((Spannable) tmp, 0, tmp.length());
+ }
+ updateStage(Stage.ConfirmWrong);
+ }
+ }
+ if (errorMsg != null) {
+ showError(errorMsg, mUiStage);
+ }
+ }
+
+ protected void setNextEnabled(boolean enabled) {
+ mNextButton.setEnabled(enabled);
+ }
+
+ protected void setNextText(int text) {
+ mNextButton.setText(text);
+ }
+
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.next_button:
+ handleNext();
+ break;
+
+ case R.id.cancel_button:
+ getActivity().finish();
+ break;
+ }
+ }
+
+ private void showError(String msg, final Stage next) {
+ mHeaderText.setText(msg);
+ mHeaderText.announceForAccessibility(mHeaderText.getText());
+ Message mesg = mHandler.obtainMessage(MSG_SHOW_ERROR, next);
+ mHandler.removeMessages(MSG_SHOW_ERROR);
+ mHandler.sendMessageDelayed(mesg, ERROR_MESSAGE_TIMEOUT);
+ }
+
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ // Check if this was the result of hitting the enter or "done" key
+ if (actionId == EditorInfo.IME_NULL
+ || actionId == EditorInfo.IME_ACTION_DONE
+ || actionId == EditorInfo.IME_ACTION_NEXT) {
+ handleNext();
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Update the hint based on current Stage and length of password entry
+ */
+ private void updateUi() {
+ final boolean canInput = mSaveAndFinishWorker == null;
+ String password = mPasswordEntry.getText().toString();
+ final int length = password.length();
+ if (mUiStage == Stage.Introduction) {
+ if (length < mPasswordMinLength) {
+ String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
+ : R.string.lockpassword_pin_too_short, mPasswordMinLength);
+ mHeaderText.setText(msg);
+ setNextEnabled(false);
+ } else {
+ String error = validatePassword(password);
+ if (error != null) {
+ mHeaderText.setText(error);
+ setNextEnabled(false);
+ } else {
+ mHeaderText.setText(R.string.lockpassword_press_continue);
+ setNextEnabled(true);
+ }
+ }
+ } else {
+ mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
+ setNextEnabled(canInput && length > 0);
+ }
+ setNextText(mUiStage.buttonText);
+ mPasswordEntryInputDisabler.setInputEnabled(canInput);
+ }
+
+ public void afterTextChanged(Editable s) {
+ // Changing the text while error displayed resets to NeedToConfirm state
+ if (mUiStage == Stage.ConfirmWrong) {
+ mUiStage = Stage.NeedToConfirm;
+ }
+ updateUi();
+ }
+
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ private void startSaveAndFinish() {
+ if (mSaveAndFinishWorker != null) {
+ Log.w(TAG, "startSaveAndFinish with an existing SaveAndFinishWorker.");
+ return;
+ }
+
+ mPasswordEntryInputDisabler.setInputEnabled(false);
+ setNextEnabled(false);
+
+ mSaveAndFinishWorker = new SaveAndFinishWorker();
+ getFragmentManager().beginTransaction().add(mSaveAndFinishWorker,
+ FRAGMENT_TAG_SAVE_AND_FINISH).commit();
+ mSaveAndFinishWorker.setListener(this);
+
+ final boolean required = getActivity().getIntent().getBooleanExtra(
+ EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
+ mSaveAndFinishWorker.start(mLockPatternUtils, required, mHasChallenge, mChallenge,
+ mChosenPassword, mCurrentPassword, mRequestedQuality);
+ }
+
+ @Override
+ public void onChosenLockSaveFinished(boolean wasSecureBefore, Intent resultData) {
+ getActivity().setResult(RESULT_FINISHED, resultData);
+ getActivity().finish();
+
+ if (!wasSecureBefore) {
+ Intent intent = getRedactionInterstitialIntent(getActivity());
+ if (intent != null) {
+ startActivity(intent);
+ }
+ }
+ }
+ }
+
+ private static class SaveAndFinishWorker extends SaveChosenLockWorkerBase {
+
+ private String mChosenPassword;
+ private String mCurrentPassword;
+ private int mRequestedQuality;
+
+ public void start(LockPatternUtils utils, boolean required,
+ boolean hasChallenge, long challenge,
+ String chosenPassword, String currentPassword, int requestedQuality) {
+ prepare(utils, required, hasChallenge, challenge);
+
+ mChosenPassword = chosenPassword;
+ mCurrentPassword = currentPassword;
+ mRequestedQuality = requestedQuality;
+
+ start();
+ }
+
+ @Override
+ protected Intent saveAndVerifyInBackground() {
+ Intent result = null;
+ final int userId = UserHandle.myUserId();
+ mUtils.setCredentialRequiredToDecrypt(true);
+ mUtils.setSeparateEncryptionPassword(mChosenPassword);
+
+ if (mHasChallenge) {
+ byte[] token;
+ try {
+ token = mUtils.verifyPassword(mChosenPassword, mChallenge, userId);
+ } catch (RequestThrottledException e) {
+ token = null;
+ }
+
+ if (token == null) {
+ Log.e(TAG, "critical: no token returned for known good password.");
+ }
+
+ result = new Intent();
+ result.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/src/com/android/settings/DevelopmentSettings.java b/src/com/android/settings/DevelopmentSettings.java
index b5b89cb..d6b1d92 100644
--- a/src/com/android/settings/DevelopmentSettings.java
+++ b/src/com/android/settings/DevelopmentSettings.java
@@ -779,7 +779,7 @@ public class DevelopmentSettings extends SettingsPreferenceFragment
private void updateAdvancedRebootOptions() {
mAdvancedReboot.setChecked(CMSettings.Secure.getInt(getActivity().getContentResolver(),
- CMSettings.Secure.ADVANCED_REBOOT, 0) != 0);
+ CMSettings.Secure.ADVANCED_REBOOT, 1) != 0);
}
private void resetDevelopmentShortcutOptions() {
diff --git a/src/com/android/settings/ReplaceEncryptionPassword.java b/src/com/android/settings/ReplaceEncryptionPassword.java
new file mode 100644
index 0000000..b6869d8
--- /dev/null
+++ b/src/com/android/settings/ReplaceEncryptionPassword.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2015 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 com.android.internal.widget.LockPatternUtils;
+import com.android.internal.widget.LockPatternUtils.RequestThrottledException;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.storage.StorageManager;
+import android.os.UserHandle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class ReplaceEncryptionPassword extends SettingsActivity {
+ @Override
+ public Intent getIntent() {
+ Intent modIntent = new Intent(super.getIntent());
+ modIntent.putExtra(EXTRA_SHOW_FRAGMENT, getFragmentClass().getName());
+ return modIntent;
+ }
+
+ @Override
+ protected boolean isValidFragment(String fragmentName) {
+ if (ReplaceEncryptionPasswordFragment.class.getName().equals(fragmentName)) return true;
+ return false;
+ }
+
+ /* package */ Class<? extends Fragment> getFragmentClass() {
+ return ReplaceEncryptionPasswordFragment.class;
+ }
+
+ public static class ReplaceEncryptionPasswordFragment extends Fragment {
+ private static final int KEYGUARD_REQUEST = 55;
+ private byte mPatternSize = LockPatternUtils.PATTERN_SIZE_DEFAULT;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ if (!(getActivity() instanceof ReplaceEncryptionPassword)) {
+ throw new SecurityException("Fragment contained in wrong activity");
+ }
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
+ Resources res = getActivity().getResources();
+ ChooseLockSettingsHelper helper = new ChooseLockSettingsHelper(getActivity(), this);
+
+ helper.launchConfirmationActivity(KEYGUARD_REQUEST,
+ res.getText(R.string.unlock_set_unlock_password_title),
+ true);
+
+ return null;
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ super.onActivityResult(requestCode, resultCode, data);
+ final int userId = UserHandle.myUserId();
+
+ if (requestCode != KEYGUARD_REQUEST) {
+ return;
+ }
+
+ // If the user entered a valid keyguard trace, present the final
+ // confirmation prompt; otherwise, go back to the initial state.
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ LockPatternUtils utils = new LockPatternUtils(getActivity());
+ int type = data.getIntExtra(ChooseLockSettingsHelper.EXTRA_KEY_TYPE, -1);
+ String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
+ if (type == StorageManager.CRYPT_TYPE_PATTERN) {
+ mPatternSize = getActivity().getIntent().getByteExtra("pattern_size",
+ LockPatternUtils.PATTERN_SIZE_DEFAULT);
+
+ utils.replaceSeparateEncryptionPasswordWithPattern(
+ utils.stringToPattern(password,
+ mPatternSize), userId);
+ } else {
+ utils.replaceSeparateEncryptionPassword(password);
+ }
+ }
+
+ getActivity().finish();
+ }
+ }
+}
diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java
index 7db4a4e..6977672 100644
--- a/src/com/android/settings/SecuritySettings.java
+++ b/src/com/android/settings/SecuritySettings.java
@@ -98,6 +98,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final String KEY_VISIBLE_ERROR_PATTERN = "visible_error_pattern";
private static final String KEY_VISIBLE_DOTS = "visibledots";
private static final String KEY_SECURITY_CATEGORY = "security_category";
+ private static final String KEY_ENCRYPTION_CATEGORY = "encryption_category";
private static final String KEY_DEVICE_ADMIN_CATEGORY = "device_admin_category";
private static final String KEY_LOCK_AFTER_TIMEOUT = "lock_after_timeout";
private static final String KEY_OWNER_INFO_SETTINGS = "owner_info_settings";
@@ -127,6 +128,7 @@ public class SecuritySettings extends SettingsPreferenceFragment
private static final String KEY_GENERAL_CATEGORY = "general_category";
private static final String KEY_LIVE_LOCK_SCREEN = "live_lock_screen";
private static final String KEY_LOCK_SCREEN_BLUR = CMSettings.Secure.LOCK_SCREEN_BLUR_ENABLED;
+ private static final String KEY_REPLACE_ENCRYPTION_PASSWORD = "crypt_keeper_replace_password";
// These switch preferences need special handling since they're not all stored in Settings.
private static final String SWITCH_PREFERENCE_KEYS[] = { KEY_LOCK_AFTER_TIMEOUT,
@@ -300,6 +302,15 @@ public class SecuritySettings extends SettingsPreferenceFragment
if (LockPatternUtils.isDeviceEncryptionEnabled()) {
// The device is currently encrypted.
addPreferencesFromResource(R.xml.security_settings_encrypted);
+ if (!mLockPatternUtils.isSeparateEncryptionPasswordEnabled()) {
+ PreferenceGroup encryptionCategory =
+ (PreferenceGroup) root.findPreference(KEY_ENCRYPTION_CATEGORY);
+ if (encryptionCategory != null) {
+ Preference replaceEncryptionPassword =
+ root.findPreference(KEY_REPLACE_ENCRYPTION_PASSWORD);
+ encryptionCategory.removePreference(replaceEncryptionPassword);
+ }
+ }
} else {
// This device supports encryption but isn't encrypted.
addPreferencesFromResource(R.xml.security_settings_unencrypted);
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index 0834b4f..a52af29 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -122,7 +122,6 @@ public class Settings extends SettingsActivity {
public static class DisplayRotationActivity extends SettingsActivity { /* empty */ }
public static class BlacklistSettingsActivity extends SettingsActivity { /* empty */ }
public static class ProfilesSettingsActivity extends SettingsActivity { /* empty */ }
- public static class AnonymousStatsActivity extends Settings { /* empty */ }
public static class ContributorsCloudActivity extends SettingsActivity { /* empty */ }
public static class CMSoundSettingsActivity extends SettingsActivity { /* empty */ }
public static class LockScreenSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SettingsActivity.java b/src/com/android/settings/SettingsActivity.java
index b54d771..d5c53a4 100644
--- a/src/com/android/settings/SettingsActivity.java
+++ b/src/com/android/settings/SettingsActivity.java
@@ -1250,9 +1250,7 @@ public class SettingsActivity extends Activity
}
private void updateTilesList(List<DashboardCategory> target) {
- final boolean showDev = mDevelopmentPreferences.getBoolean(
- DevelopmentSettings.PREF_SHOW,
- android.os.Build.TYPE.equals("eng"));
+ final boolean showDev = true;
final UserManager um = (UserManager) getSystemService(Context.USER_SERVICE);
diff --git a/src/com/android/settings/cmstats/AnonymousStats.java b/src/com/android/settings/cmstats/AnonymousStats.java
deleted file mode 100644
index 54e124d..0000000
--- a/src/com/android/settings/cmstats/AnonymousStats.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2015 The CyanogenMod Project
- * (C) 2017 The LineageOS 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.cmstats;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-
-import org.cyanogenmod.internal.logging.CMMetricsLogger;
-
-public class AnonymousStats extends SettingsPreferenceFragment {
-
- private static final String PREF_FILE_NAME = "CMStats";
- /* package */ static final String ANONYMOUS_OPT_IN = "pref_anonymous_opt_in";
- /* package */ static final String ANONYMOUS_LAST_CHECKED = "pref_anonymous_checked_in";
-
- /* package */ static final String KEY_LAST_JOB_ID = "last_job_id";
- /* package */ static final int QUEUE_MAX_THRESHOLD = 1000;
-
- public static SharedPreferences getPreferences(Context context) {
- return context.getSharedPreferences(PREF_FILE_NAME, 0);
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- addPreferencesFromResource(R.xml.anonymous_stats);
- }
-
- public static void updateLastSynced(Context context) {
- getPreferences(context)
- .edit()
- .putLong(ANONYMOUS_LAST_CHECKED,System.currentTimeMillis())
- .commit();
- }
-
- private static int getLastJobId(Context context) {
- return getPreferences(context).getInt(KEY_LAST_JOB_ID, 0);
- }
-
- private static void setLastJobId(Context context, int id) {
- getPreferences(context)
- .edit()
- .putInt(KEY_LAST_JOB_ID, id)
- .commit();
- }
-
- public static int getNextJobId(Context context) {
- int lastId = getLastJobId(context);
- if (lastId >= QUEUE_MAX_THRESHOLD) {
- lastId = 1;
- } else {
- lastId += 1;
- }
- setLastJobId(context, lastId);
- return lastId;
- }
-
- @Override
- protected int getMetricsCategory() {
- return CMMetricsLogger.ANONYMOUS_STATS;
- }
-}
diff --git a/src/com/android/settings/cmstats/PreviewData.java b/src/com/android/settings/cmstats/PreviewData.java
deleted file mode 100644
index 0adacad..0000000
--- a/src/com/android/settings/cmstats/PreviewData.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2012 The CyanogenMod 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.cmstats;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.preference.Preference;
-import android.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import org.cyanogenmod.internal.logging.CMMetricsLogger;
-
-public class PreviewData extends SettingsPreferenceFragment {
- private static final String UNIQUE_ID = "preview_id";
- private static final String DEVICE = "preview_device";
- private static final String VERSION = "preview_version";
- private static final String COUNTRY = "preview_country";
- private static final String CARRIER = "preview_carrier";
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- addPreferencesFromResource(R.xml.preview_data);
-
- final PreferenceScreen prefSet = getPreferenceScreen();
- final Context context = getActivity();
-
- prefSet.findPreference(UNIQUE_ID).setSummary(Utilities.getUniqueID(context));
- prefSet.findPreference(DEVICE).setSummary(Utilities.getDevice());
- prefSet.findPreference(VERSION).setSummary(Utilities.getModVersion());
- prefSet.findPreference(COUNTRY).setSummary(Utilities.getCountryCode(context));
- prefSet.findPreference(CARRIER).setSummary(Utilities.getCarrier(context));
- }
-
- @Override
- protected int getMetricsCategory() {
- return CMMetricsLogger.PREVIEW_DATA;
- }
-}
diff --git a/src/com/android/settings/cmstats/ReportingService.java b/src/com/android/settings/cmstats/ReportingService.java
deleted file mode 100644
index f04786d..0000000
--- a/src/com/android/settings/cmstats/ReportingService.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2015 The CyanogenMod Project
- * (C) 2017 The LineageOS 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.cmstats;
-
-import android.app.IntentService;
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.os.PersistableBundle;
-import android.os.UserHandle;
-import android.util.Log;
-import cyanogenmod.providers.CMSettings;
-
-import java.util.List;
-
-public class ReportingService extends IntentService {
- /* package */ static final String TAG = "CMStats";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- public ReportingService() {
- super(ReportingService.class.getSimpleName());
- }
-
- @Override
- protected void onHandleIntent(Intent intent) {
- JobScheduler js = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
-
- String deviceId = Utilities.getUniqueID(getApplicationContext());
- String deviceName = Utilities.getDevice();
- String deviceVersion = Utilities.getModVersion();
- String deviceCountry = Utilities.getCountryCode(getApplicationContext());
- String deviceCarrier = Utilities.getCarrier(getApplicationContext());
- String deviceCarrierId = Utilities.getCarrierId(getApplicationContext());
-
- final int cmOrgJobId = AnonymousStats.getNextJobId(getApplicationContext());
-
- if (DEBUG) Log.d(TAG, "scheduling job id: " + cmOrgJobId);
-
- PersistableBundle cmBundle = new PersistableBundle();
- cmBundle.putString(StatsUploadJobService.KEY_DEVICE_NAME, deviceName);
- cmBundle.putString(StatsUploadJobService.KEY_UNIQUE_ID, deviceId);
- cmBundle.putString(StatsUploadJobService.KEY_VERSION, deviceVersion);
- cmBundle.putString(StatsUploadJobService.KEY_COUNTRY, deviceCountry);
- cmBundle.putString(StatsUploadJobService.KEY_CARRIER, deviceCarrier);
- cmBundle.putString(StatsUploadJobService.KEY_CARRIER_ID, deviceCarrierId);
- cmBundle.putLong(StatsUploadJobService.KEY_TIMESTAMP, System.currentTimeMillis());
-
- // set job types
- cmBundle.putInt(StatsUploadJobService.KEY_JOB_TYPE,
- StatsUploadJobService.JOB_TYPE_CMORG);
-
- // schedule cmorg stats upload
- js.schedule(new JobInfo.Builder(cmOrgJobId, new ComponentName(getPackageName(),
- StatsUploadJobService.class.getName()))
- .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
- .setMinimumLatency(1000)
- .setExtras(cmBundle)
- .setPersisted(true)
- .build());
-
- // reschedule
- AnonymousStats.updateLastSynced(this);
- ReportingServiceManager.setAlarm(this);
- }
-}
diff --git a/src/com/android/settings/cmstats/ReportingServiceManager.java b/src/com/android/settings/cmstats/ReportingServiceManager.java
deleted file mode 100644
index 286618c..0000000
--- a/src/com/android/settings/cmstats/ReportingServiceManager.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2012 The CyanogenMod Project
- * (C) 2017 The LineageOS 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.cmstats;
-
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.app.job.JobScheduler;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.UserHandle;
-import android.util.Log;
-import cyanogenmod.providers.CMSettings;
-
-public class ReportingServiceManager extends BroadcastReceiver {
- private static final long MILLIS_PER_HOUR = 60L * 60L * 1000L;
- private static final long MILLIS_PER_DAY = 24L * MILLIS_PER_HOUR;
- private static final long UPDATE_INTERVAL = 1L * MILLIS_PER_DAY;
-
- private static final String TAG = ReportingServiceManager.class.getSimpleName();
-
- public static final String ACTION_LAUNCH_SERVICE =
- "com.android.settings.action.TRIGGER_REPORT_METRICS";
- public static final String EXTRA_FORCE = "force";
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
- setAlarm(context);
- } else if (intent.getAction().equals(ACTION_LAUNCH_SERVICE)){
- launchService(context, intent.getBooleanExtra(EXTRA_FORCE, false));
- }
- }
-
- public static void setAlarm(Context context) {
- SharedPreferences prefs = AnonymousStats.getPreferences(context);
- if (prefs.contains(AnonymousStats.ANONYMOUS_OPT_IN)) {
- migrate(context, prefs);
- }
- if (!Utilities.isStatsCollectionEnabled(context)) {
- return;
- }
- long lastSynced = prefs.getLong(AnonymousStats.ANONYMOUS_LAST_CHECKED, 0);
- if (lastSynced == 0) {
- launchService(context, true); // service will reschedule the next alarm
- return;
- }
- long millisFromNow = (lastSynced + UPDATE_INTERVAL) - System.currentTimeMillis();
-
- Intent intent = new Intent(ACTION_LAUNCH_SERVICE);
- intent.setClass(context, ReportingServiceManager.class);
-
- AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
- alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + millisFromNow,
- PendingIntent.getBroadcast(context, 0, intent, 0));
- Log.d(TAG, "Next sync attempt in : "
- + (millisFromNow / MILLIS_PER_HOUR) + " hours");
- }
-
- public static void launchService(Context context, boolean force) {
- SharedPreferences prefs = AnonymousStats.getPreferences(context);
-
- if (!Utilities.isStatsCollectionEnabled(context)) {
- return;
- }
-
- if (!force) {
- long lastSynced = prefs.getLong(AnonymousStats.ANONYMOUS_LAST_CHECKED, 0);
- if (lastSynced == 0) {
- setAlarm(context);
- return;
- }
- long timeElapsed = System.currentTimeMillis() - lastSynced;
- if (timeElapsed < UPDATE_INTERVAL) {
- long timeLeft = UPDATE_INTERVAL - timeElapsed;
- Log.d(TAG, "Waiting for next sync : "
- + timeLeft / MILLIS_PER_HOUR + " hours");
- return;
- }
- }
-
- Intent intent = new Intent();
- intent.setClass(context, ReportingService.class);
- context.startServiceAsUser(intent, UserHandle.OWNER);
- }
-
- private static void migrate(Context context, SharedPreferences prefs) {
- Utilities.setStatsCollectionEnabled(context,
- prefs.getBoolean(AnonymousStats.ANONYMOUS_OPT_IN, true));
- prefs.edit().remove(AnonymousStats.ANONYMOUS_OPT_IN).commit();
- }
-
-}
diff --git a/src/com/android/settings/cmstats/StatsUploadJobService.java b/src/com/android/settings/cmstats/StatsUploadJobService.java
deleted file mode 100644
index c84e1a1..0000000
--- a/src/com/android/settings/cmstats/StatsUploadJobService.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2015 The CyanogenMod Project
- * (C) 2017 The LineageOS 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.cmstats;
-
-import android.app.job.JobParameters;
-import android.app.job.JobService;
-import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.PersistableBundle;
-import android.util.ArrayMap;
-import android.util.Log;
-import com.android.settings.R;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.util.Collections;
-import java.util.Map;
-
-public class StatsUploadJobService extends JobService {
-
- private static final String TAG = StatsUploadJobService.class.getSimpleName();
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- public static final String KEY_JOB_TYPE = "job_type";
- public static final int JOB_TYPE_CMORG = 1;
-
- public static final String KEY_UNIQUE_ID = "uniqueId";
- public static final String KEY_DEVICE_NAME = "deviceName";
- public static final String KEY_VERSION = "version";
- public static final String KEY_COUNTRY = "country";
- public static final String KEY_CARRIER = "carrier";
- public static final String KEY_CARRIER_ID = "carrierId";
- public static final String KEY_TIMESTAMP = "timeStamp";
-
- private final Map<JobParameters, StatsUploadTask> mCurrentJobs
- = Collections.synchronizedMap(new ArrayMap<JobParameters, StatsUploadTask>());
-
- @Override
- public boolean onStartJob(JobParameters jobParameters) {
- if (DEBUG)
- Log.d(TAG, "onStartJob() called with " + "jobParameters = [" + jobParameters + "]");
-
- if (!Utilities.isStatsCollectionEnabled(this)) {
- return false;
- }
-
- final StatsUploadTask uploadTask = new StatsUploadTask(jobParameters);
- mCurrentJobs.put(jobParameters, uploadTask);
- uploadTask.execute((Void) null);
- return true;
- }
-
- @Override
- public boolean onStopJob(JobParameters jobParameters) {
- if (DEBUG)
- Log.d(TAG, "onStopJob() called with " + "jobParameters = [" + jobParameters + "]");
-
- final StatsUploadTask cancelledJob;
- cancelledJob = mCurrentJobs.remove(jobParameters);
-
- if (cancelledJob != null) {
- // cancel the ongoing background task
- cancelledJob.cancel(true);
- return true; // reschedule
- }
-
- return false;
- }
-
- private class StatsUploadTask extends AsyncTask<Void, Void, Boolean> {
-
- private JobParameters mJobParams;
-
- public StatsUploadTask(JobParameters jobParams) {
- this.mJobParams = jobParams;
- }
-
- @Override
- protected Boolean doInBackground(Void... params) {
-
- PersistableBundle extras = mJobParams.getExtras();
-
- String deviceId = extras.getString(KEY_UNIQUE_ID);
- String deviceName = extras.getString(KEY_DEVICE_NAME);
- String deviceVersion = extras.getString(KEY_VERSION);
- String deviceCountry = extras.getString(KEY_COUNTRY);
- String deviceCarrier = extras.getString(KEY_CARRIER);
- String deviceCarrierId = extras.getString(KEY_CARRIER_ID);
- long timeStamp = extras.getLong(KEY_TIMESTAMP);
-
- boolean success = false;
- int jobType = extras.getInt(KEY_JOB_TYPE, -1);
- if (!isCancelled()) {
- switch (jobType) {
- case JOB_TYPE_CMORG:
- try {
- JSONObject json = buildStatsRequest(deviceId, deviceName,
- deviceVersion, deviceCountry, deviceCarrier, deviceCarrierId);
- success = uploadToCM(json);
- } catch (IOException | JSONException e) {
- Log.e(TAG, "Could not upload stats checkin to community server", e);
- success = false;
- }
- break;
- }
- }
- if (DEBUG)
- Log.d(TAG, "job id " + mJobParams.getJobId() + ", has finished with success="
- + success);
- return success;
- }
-
- @Override
- protected void onPostExecute(Boolean success) {
- mCurrentJobs.remove(mJobParams);
- jobFinished(mJobParams, !success);
- }
- }
-
- private JSONObject buildStatsRequest(String deviceId, String deviceName, String deviceVersion,
- String deviceCountry, String deviceCarrier,
- String deviceCarrierId) throws JSONException {
- JSONObject request = new JSONObject();
- request.put("device_hash", deviceId);
- request.put("device_name", deviceName);
- request.put("device_version", deviceVersion);
- request.put("device_country", deviceCountry);
- request.put("device_carrier", deviceCarrier);
- request.put("device_carrier_id", deviceCarrierId);
- return request;
- }
-
- private boolean uploadToCM(JSONObject json) throws IOException {
- final Uri uri = Uri.parse(getString(R.string.stats_cm_url));
- URL url = new URL(uri.toString());
- HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
- try {
- urlConnection.setInstanceFollowRedirects(true);
- urlConnection.setDoOutput(true);
- urlConnection.setDoInput(true);
- urlConnection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
-
- OutputStream os = urlConnection.getOutputStream();
- os.write(json.toString().getBytes("UTF-8"));
- os.close();
-
- final int responseCode = urlConnection.getResponseCode();
- if (DEBUG) Log.d(TAG, "cm server response code=" + responseCode);
- final boolean success = responseCode == HttpURLConnection.HTTP_OK;
- if (!success) {
- Log.w(TAG, "failed sending, server returned: " + getResponse(urlConnection,
- !success));
- }
- return success;
- } finally {
- urlConnection.disconnect();
- }
-
- }
-
- private String getResponse(HttpURLConnection httpUrlConnection, boolean errorStream)
- throws IOException {
- InputStream responseStream = new BufferedInputStream(errorStream
- ? httpUrlConnection.getErrorStream()
- : httpUrlConnection.getInputStream());
-
- BufferedReader responseStreamReader = new BufferedReader(
- new InputStreamReader(responseStream));
- String line = "";
- StringBuilder stringBuilder = new StringBuilder();
- while ((line = responseStreamReader.readLine()) != null) {
- stringBuilder.append(line).append("\n");
- }
- responseStreamReader.close();
- responseStream.close();
-
- return stringBuilder.toString();
- }
-
-}
diff --git a/src/com/android/settings/cmstats/Utilities.java b/src/com/android/settings/cmstats/Utilities.java
deleted file mode 100644
index f69e8ca..0000000
--- a/src/com/android/settings/cmstats/Utilities.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2012 The CyanogenMod 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.cmstats;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.telephony.TelephonyManager;
-import android.text.TextUtils;
-
-import cyanogenmod.providers.CMSettings;
-
-import java.math.BigInteger;
-import java.net.NetworkInterface;
-import java.security.MessageDigest;
-
-public class Utilities {
- public static String getUniqueID(Context context) {
- final String id = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
- return digest(context.getPackageName() + id);
- }
-
- public static String getCarrier(Context context) {
- TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- String carrier = tm.getNetworkOperatorName();
- if (TextUtils.isEmpty(carrier)) {
- carrier = "Unknown";
- }
- return carrier;
- }
-
- public static String getCarrierId(Context context) {
- TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- String carrierId = tm.getNetworkOperator();
- if (TextUtils.isEmpty(carrierId)) {
- carrierId = "0";
- }
- return carrierId;
- }
-
- public static String getCountryCode(Context context) {
- TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- String countryCode = tm.getNetworkCountryIso();
- if (TextUtils.isEmpty(countryCode)) {
- countryCode = "Unknown";
- }
- return countryCode;
- }
-
- public static String getDevice() {
- return SystemProperties.get("ro.cm.device", Build.PRODUCT);
- }
-
- public static String getModVersion() {
- return SystemProperties.get("ro.cm.version", Build.DISPLAY);
- }
-
- public static String digest(String input) {
- try {
- MessageDigest md = MessageDigest.getInstance("SHA-256");
- return new BigInteger(1, md.digest(input.getBytes())).toString(16).toUpperCase();
- } catch (Exception e) {
- return null;
- }
- }
-
- /**
- * Check to see if global stats are enabled.
- * @param context
- * @return Whether or not stats collection is enabled.
- */
- public static boolean isStatsCollectionEnabled(Context context) {
- return CMSettings.Secure.getInt(context.getContentResolver(),
- CMSettings.Secure.STATS_COLLECTION, 1) != 0;
- }
-
- /**
- * Enabled or disable stats collection
- * @param context
- * @param enabled Boolean that sets collection being enabled.
- */
- public static void setStatsCollectionEnabled(Context context, boolean enabled) {
- int enable = (enabled) ? 1 : 0;
- CMSettings.Secure.putInt(context.getContentResolver(),
- CMSettings.Secure.STATS_COLLECTION, enable);
- }
-}