From 9e4ebaf5d1f746565f099269f9fb3674696bedbe Mon Sep 17 00:00:00 2001 From: Danesh M Date: Wed, 2 Dec 2015 16:08:08 -0800 Subject: Settings : Port over reorganization from 12.1 Change-Id: I3d77bb96aba4a501d3223e72be60403694828a34 --- src/com/android/settings/ButtonSettings.java | 11 +- src/com/android/settings/DisplaySettings.java | 71 ++- src/com/android/settings/SecuritySettings.java | 259 ++++---- src/com/android/settings/Settings.java | 4 +- src/com/android/settings/SettingsActivity.java | 29 +- src/com/android/settings/WirelessSettings.java | 12 +- .../settings/cyanogenmod/DisplayRotation.java | 2 +- .../notification/NotificationManagerSettings.java | 136 ++++ .../notification/NotificationSettings.java | 705 --------------------- .../settings/notification/SoundSettings.java | 608 ++++++++++++++++++ .../notification/VolumeSeekBarPreference.java | 8 +- .../settings/search/IndexDatabaseHelper.java | 2 +- src/com/android/settings/search/Ranking.java | 6 +- .../settings/search/SearchIndexableResources.java | 23 +- 14 files changed, 1004 insertions(+), 872 deletions(-) create mode 100644 src/com/android/settings/notification/NotificationManagerSettings.java delete mode 100644 src/com/android/settings/notification/NotificationSettings.java create mode 100644 src/com/android/settings/notification/SoundSettings.java (limited to 'src/com') diff --git a/src/com/android/settings/ButtonSettings.java b/src/com/android/settings/ButtonSettings.java index 5886a3f..a5a7d35 100644 --- a/src/com/android/settings/ButtonSettings.java +++ b/src/com/android/settings/ButtonSettings.java @@ -78,7 +78,6 @@ public class ButtonSettings extends SettingsPreferenceFragment implements private static final String KEY_NAVIGATION_RECENTS_LONG_PRESS = "navigation_recents_long_press"; private static final String KEY_POWER_END_CALL = "power_end_call"; private static final String KEY_HOME_ANSWER_CALL = "home_answer_call"; - private static final String KEY_BLUETOOTH_INPUT_SETTINGS = "bluetooth_input_settings"; private static final String KEY_VOLUME_MUSIC_CONTROLS = "volbtn_music_controls"; private static final String KEY_VOLUME_CONTROL_RING_STREAM = "volume_keys_control_ring_stream"; @@ -91,7 +90,7 @@ public class ButtonSettings extends SettingsPreferenceFragment implements private static final String CATEGORY_CAMERA = "camera_key"; private static final String CATEGORY_VOLUME = "volume_keys"; private static final String CATEGORY_BACKLIGHT = "key_backlight"; - private static final String CATEGORY_NAVBAR = "navigation_bar"; + private static final String CATEGORY_NAVBAR = "navigation_bar_category"; // Available custom actions to perform on a key press. // Must match values for KEY_HOME_LONG_PRESS_ACTION in: @@ -380,7 +379,9 @@ public class ButtonSettings extends SettingsPreferenceFragment implements CMSettings.System.SWAP_VOLUME_KEYS_ON_ROTATION, 0); mSwapVolumeButtons = (SwitchPreference) prefScreen.findPreference(KEY_SWAP_VOLUME_BUTTONS); - mSwapVolumeButtons.setChecked(swapVolumeKeys > 0); + if (mSwapVolumeButtons != null) { + mSwapVolumeButtons.setChecked(swapVolumeKeys > 0); + } } else { prefScreen.removePreference(volumeCategory); } @@ -412,9 +413,6 @@ public class ButtonSettings extends SettingsPreferenceFragment implements prefScreen.removePreference(backlight); } - Utils.updatePreferenceToSpecificActivityFromMetaDataOrRemove(getActivity(), - getPreferenceScreen(), KEY_BLUETOOTH_INPUT_SETTINGS); - if (mCameraWakeScreen != null) { if (mCameraSleepOnRelease != null && !getResources().getBoolean( com.android.internal.R.bool.config_singleStageCameraKey)) { @@ -468,6 +466,7 @@ public class ButtonSettings extends SettingsPreferenceFragment implements private ListPreference initActionList(String key, int value) { ListPreference list = (ListPreference) getPreferenceScreen().findPreference(key); + if (list == null) return null; list.setValue(Integer.toString(value)); list.setSummary(list.getEntry()); list.setOnPreferenceChangeListener(this); diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java index 9758848..f651ead 100644 --- a/src/com/android/settings/DisplaySettings.java +++ b/src/com/android/settings/DisplaySettings.java @@ -91,6 +91,9 @@ public class DisplaySettings extends SettingsPreferenceFragment implements /** If there is no setting in the provider, use this. */ private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000; + private static final String KEY_CATEGORY_LIGHTS = "lights"; + private static final String KEY_CATEGORY_DISPLAY = "display"; + private static final String KEY_CATEGORY_INTERFACE = "interface"; private static final String KEY_SCREEN_TIMEOUT = "screen_timeout"; private static final String KEY_LCD_DENSITY = "lcd_density"; private static final String KEY_FONT_SIZE = "font_size"; @@ -107,6 +110,8 @@ public class DisplaySettings extends SettingsPreferenceFragment implements private static final String KEY_PROXIMITY_WAKE = "proximity_on_wake"; private static final String KEY_DISPLAY_ROTATION = "display_rotation"; private static final String KEY_WAKE_WHEN_PLUGGED_OR_UNPLUGGED = "wake_when_plugged_or_unplugged"; + private static final String KEY_NOTIFICATION_LIGHT = "notification_light"; + private static final String KEY_BATTERY_LIGHT = "battery_light"; private static final int DLG_GLOBAL_CHANGE_WARNING = 1; @@ -119,6 +124,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements private ListPreference mScreenTimeoutPreference; private ListPreference mNightModePreference; private Preference mScreenSaverPreference; + private SwitchPreference mAccelerometer; private SwitchPreference mLiftToWakePreference; private SwitchPreference mDozePreference; private SwitchPreference mTapToWakePreference; @@ -130,6 +136,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements @Override public void onChange(boolean selfChange) { updateDisplayRotationPreferenceDescription(); + updateAccelerometerRotationSwitch(); } }; @@ -153,15 +160,23 @@ public class DisplaySettings extends SettingsPreferenceFragment implements super.onCreate(savedInstanceState); final Activity activity = getActivity(); final ContentResolver resolver = activity.getContentResolver(); - addPreferencesFromResource(R.xml.display_settings); + addPreferencesFromResource(R.xml.display); + PreferenceCategory displayPrefs = (PreferenceCategory) + findPreference(KEY_CATEGORY_DISPLAY); + PreferenceCategory interfacePrefs = (PreferenceCategory) + findPreference(KEY_CATEGORY_INTERFACE); mDisplayRotationPreference = (PreferenceScreen) findPreference(KEY_DISPLAY_ROTATION); + mAccelerometer = (SwitchPreference) findPreference(DisplayRotation.KEY_ACCELEROMETER); + if (mAccelerometer != null) { + mAccelerometer.setPersistent(false); + } mScreenSaverPreference = findPreference(KEY_SCREEN_SAVER); if (mScreenSaverPreference != null && getResources().getBoolean( com.android.internal.R.bool.config_dreamsSupported) == false) { - getPreferenceScreen().removePreference(mScreenSaverPreference); + interfacePrefs.removePreference(mScreenSaverPreference); } mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT); @@ -176,7 +191,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements mLcdDensityPreference = (ListPreference) findPreference(KEY_LCD_DENSITY); if (mLcdDensityPreference != null) { if (UserHandle.myUserId() != UserHandle.USER_OWNER) { - getPreferenceScreen().removePreference(mLcdDensityPreference); + interfacePrefs.removePreference(mLcdDensityPreference); } else { int defaultDensity = getDefaultDensity(); int currentDensity = getCurrentDensity(); @@ -220,8 +235,8 @@ public class DisplaySettings extends SettingsPreferenceFragment implements if (mAutoBrightnessPreference != null && isAutomaticBrightnessAvailable(getResources())) { mAutoBrightnessPreference.setOnPreferenceChangeListener(this); } else { - if (mAutoBrightnessPreference != null) { - removePreference(KEY_AUTO_BRIGHTNESS); + if (displayPrefs != null && mAutoBrightnessPreference != null) { + displayPrefs.removePreference(mAutoBrightnessPreference); mAutoBrightnessPreference = null; } } @@ -230,8 +245,8 @@ public class DisplaySettings extends SettingsPreferenceFragment implements if (mLiftToWakePreference != null && isLiftToWakeAvailable(activity)) { mLiftToWakePreference.setOnPreferenceChangeListener(this); } else { - if (mLiftToWakePreference != null) { - removePreference(KEY_LIFT_TO_WAKE); + if (displayPrefs != null && mLiftToWakePreference != null) { + displayPrefs.removePreference(mLiftToWakePreference); mLiftToWakePreference = null; } } @@ -240,7 +255,9 @@ public class DisplaySettings extends SettingsPreferenceFragment implements if (mDozePreference != null && Utils.isDozeAvailable(activity)) { mDozePreference.setOnPreferenceChangeListener(this); } else { - removePreference(KEY_DOZE); + if (displayPrefs != null && mDozePreference != null) { + displayPrefs.removePreference(mDozePreference); + } } if (isCameraGestureAvailable(getResources())) { @@ -283,6 +300,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements mWakeWhenPluggedOrUnplugged = (SwitchPreference) findPreference(KEY_WAKE_WHEN_PLUGGED_OR_UNPLUGGED); + initPulse((PreferenceCategory) findPreference(KEY_CATEGORY_LIGHTS)); } private int getDefaultDensity() { @@ -325,6 +343,11 @@ public class DisplaySettings extends SettingsPreferenceFragment implements return res.getBoolean(com.android.internal.R.bool.config_automatic_brightness_available); } + private void updateAccelerometerRotationSwitch() { + if (mAccelerometer != null) { + mAccelerometer.setChecked(!RotationPolicy.isRotationLocked(getActivity())); + } + } private void updateDisplayRotationPreferenceDescription() { if (mDisplayRotationPreference == null) { // The preference was removed, do nothing @@ -477,11 +500,14 @@ public class DisplaySettings extends SettingsPreferenceFragment implements boolean wakeUpWhenPluggedOrUnpluggedConfig = getResources().getBoolean( com.android.internal.R.bool.config_unplugTurnsOnScreen); + if (mWakeWhenPluggedOrUnplugged != null) { mWakeWhenPluggedOrUnplugged.setChecked(CMSettings.Global.getInt(getContentResolver(), CMSettings.Global.WAKE_WHEN_PLUGGED_OR_UNPLUGGED, (wakeUpWhenPluggedOrUnpluggedConfig ? 1 : 0)) == 1); + } updateState(); + updateAccelerometerRotationSwitch(); } @Override @@ -600,6 +626,22 @@ public class DisplaySettings extends SettingsPreferenceFragment implements task.execute(); } + // === Pulse notification light === + + private void initPulse(PreferenceCategory parent) { + if (!getResources().getBoolean( + com.android.internal.R.bool.config_intrusiveNotificationLed)) { + parent.removePreference(parent.findPreference(KEY_NOTIFICATION_LIGHT)); + } + if (!getResources().getBoolean( + com.android.internal.R.bool.config_intrusiveBatteryLed) + || UserHandle.myUserId() != UserHandle.USER_OWNER) { + parent.removePreference(parent.findPreference(KEY_BATTERY_LIGHT)); + } + if (parent.getPreferenceCount() == 0) { + getPreferenceScreen().removePreference(parent); + } + } /** * Reads the current font size and sets the value in the summary text */ @@ -632,6 +674,9 @@ public class DisplaySettings extends SettingsPreferenceFragment implements CMSettings.Global.WAKE_WHEN_PLUGGED_OR_UNPLUGGED, mWakeWhenPluggedOrUnplugged.isChecked() ? 1 : 0); return true; + } else if (preference == mAccelerometer) { + RotationPolicy.setRotationLockForAccessibility(getActivity(), + !mAccelerometer.isChecked()); } return super.onPreferenceTreeClick(preferenceScreen, preference); @@ -729,7 +774,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements new ArrayList(); SearchIndexableResource sir = new SearchIndexableResource(context); - sir.xmlResId = R.xml.display_settings; + sir.xmlResId = R.xml.display; result.add(sir); return result; @@ -742,6 +787,14 @@ public class DisplaySettings extends SettingsPreferenceFragment implements com.android.internal.R.bool.config_dreamsSupported)) { result.add(KEY_SCREEN_SAVER); } + if (!context.getResources().getBoolean( + com.android.internal.R.bool.config_intrusiveNotificationLed)) { + result.add(KEY_NOTIFICATION_LIGHT); + } + if (!context.getResources().getBoolean( + com.android.internal.R.bool.config_intrusiveBatteryLed)) { + result.add(KEY_BATTERY_LIGHT); + } if (!isAutomaticBrightnessAvailable(context.getResources())) { result.add(KEY_AUTO_BRIGHTNESS); } diff --git a/src/com/android/settings/SecuritySettings.java b/src/com/android/settings/SecuritySettings.java index 308bea5..c0e5b73 100644 --- a/src/com/android/settings/SecuritySettings.java +++ b/src/com/android/settings/SecuritySettings.java @@ -53,6 +53,7 @@ import android.util.Log; import com.android.internal.logging.MetricsLogger; import com.android.internal.widget.LockPatternUtils; +import com.android.settings.Settings.LockScreenSettingsActivity; import com.android.settings.TrustAgentUtils.TrustAgentComponentInfo; import com.android.settings.fingerprint.FingerprintEnrollIntroduction; import com.android.settings.fingerprint.FingerprintSettings; @@ -77,6 +78,11 @@ public class SecuritySettings extends SettingsPreferenceFragment private static final Intent TRUST_AGENT_INTENT = new Intent(TrustAgentService.SERVICE_INTERFACE); + // Fitler types for this panel + private static final String FILTER_TYPE_EXTRA = "filter_type"; + private static final int TYPE_LOCKSCREEN_EXTRA = 0; + private static final int TYPE_SECURITY_EXTRA = 1; + // Lock Settings private static final String KEY_UNLOCK_SET_OR_CHANGE = "unlock_set_or_change"; private static final String KEY_VISIBLE_PATTERN = "visiblepattern"; @@ -141,6 +147,7 @@ public class SecuritySettings extends SettingsPreferenceFragment private Intent mTrustAgentClickIntent; private Preference mOwnerInfoPref; + private int mFilterType = TYPE_SECURITY_EXTRA; @Override protected int getMetricsCategory() { @@ -151,6 +158,19 @@ public class SecuritySettings extends SettingsPreferenceFragment public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + // Ugly hack for legacy shortcuts :'( + Intent intent = getActivity().getIntent(); + ComponentName componentName = intent.getComponent(); + if (componentName.getClassName().equals( + LockScreenSettingsActivity.class.getName())) { + mFilterType = TYPE_LOCKSCREEN_EXTRA; + } else { + Bundle bundle = getArguments(); + if (bundle != null) { + mFilterType = bundle.getInt(FILTER_TYPE_EXTRA, TYPE_SECURITY_EXTRA); + } + } + mSubscriptionManager = SubscriptionManager.from(getActivity()); mLockPatternUtils = new LockPatternUtils(getActivity()); @@ -210,25 +230,27 @@ public class SecuritySettings extends SettingsPreferenceFragment // Add package manager to check if features are available PackageManager pm = getPackageManager(); - // Add options for lock/unlock screen - final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils); - addPreferencesFromResource(resid); - // Add options for device encryption mIsPrimary = MY_USER_ID == UserHandle.USER_OWNER; - mOwnerInfoPref = findPreference(KEY_OWNER_INFO_SETTINGS); - if (mOwnerInfoPref != null) { - mOwnerInfoPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(Preference preference) { - OwnerInfoSettings.show(SecuritySettings.this); - return true; - } - }); + if (mFilterType == TYPE_LOCKSCREEN_EXTRA) { + // Add options for lock/unlock screen + final int resid = getResIdForLockUnlockScreen(getActivity(), mLockPatternUtils); + addPreferencesFromResource(resid); + + mOwnerInfoPref = findPreference(KEY_OWNER_INFO_SETTINGS); + if (mOwnerInfoPref != null) { + mOwnerInfoPref.setOnPreferenceClickListener(new OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + OwnerInfoSettings.show(SecuritySettings.this); + return true; + } + }); + } } - if (mIsPrimary) { + if (mIsPrimary && mFilterType == TYPE_SECURITY_EXTRA) { if (LockPatternUtils.isDeviceEncryptionEnabled()) { // The device is currently encrypted. addPreferencesFromResource(R.xml.security_settings_encrypted); @@ -238,119 +260,120 @@ public class SecuritySettings extends SettingsPreferenceFragment } } - // Fingerprint and trust agents - PreferenceGroup securityCategory = (PreferenceGroup) - root.findPreference(KEY_SECURITY_CATEGORY); - if (securityCategory != null) { - maybeAddFingerprintPreference(securityCategory); - addTrustAgentSettings(securityCategory); - } + if (mFilterType == TYPE_LOCKSCREEN_EXTRA) { + // Fingerprint and trust agents + PreferenceGroup securityCategory = (PreferenceGroup) + root.findPreference(KEY_SECURITY_CATEGORY); + if (securityCategory != null) { + maybeAddFingerprintPreference(securityCategory); + addTrustAgentSettings(securityCategory); + } - // lock after preference - mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT); - if (mLockAfter != null) { - setupLockAfterPreference(); - updateLockAfterPreferenceSummary(); - } + // lock after preference + mLockAfter = (ListPreference) root.findPreference(KEY_LOCK_AFTER_TIMEOUT); + if (mLockAfter != null) { + setupLockAfterPreference(); + updateLockAfterPreferenceSummary(); + } - // visible pattern - mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN); + // visible pattern + mVisiblePattern = (SwitchPreference) root.findPreference(KEY_VISIBLE_PATTERN); + + // lock instantly on power key press + mPowerButtonInstantlyLocks = (SwitchPreference) root.findPreference( + KEY_POWER_INSTANTLY_LOCKS); + Preference trustAgentPreference = root.findPreference(KEY_TRUST_AGENT); + if (mPowerButtonInstantlyLocks != null && + trustAgentPreference != null && + trustAgentPreference.getTitle().length() > 0) { + mPowerButtonInstantlyLocks.setSummary(getString( + R.string.lockpattern_settings_power_button_instantly_locks_summary, + trustAgentPreference.getTitle())); + } + } else { + // Append the rest of the settings + addPreferencesFromResource(R.xml.security_settings_misc); - // lock instantly on power key press - mPowerButtonInstantlyLocks = (SwitchPreference) root.findPreference( - KEY_POWER_INSTANTLY_LOCKS); - Preference trustAgentPreference = root.findPreference(KEY_TRUST_AGENT); - if (mPowerButtonInstantlyLocks != null && - trustAgentPreference != null && - trustAgentPreference.getTitle().length() > 0) { - mPowerButtonInstantlyLocks.setSummary(getString( - R.string.lockpattern_settings_power_button_instantly_locks_summary, - trustAgentPreference.getTitle())); - } + // Do not display SIM lock for devices without an Icc card + TelephonyManager tm = TelephonyManager.getDefault(); + CarrierConfigManager cfgMgr = (CarrierConfigManager) + getActivity().getSystemService(Context.CARRIER_CONFIG_SERVICE); + PersistableBundle b = cfgMgr.getConfig(); + if (!mIsPrimary || !isSimIccReady() || + b.getBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL)) { + root.removePreference(root.findPreference(KEY_SIM_LOCK)); + } else { + // Disable SIM lock if there is no ready SIM card. + root.findPreference(KEY_SIM_LOCK).setEnabled(isSimReady()); + } + if (Settings.System.getInt(getContentResolver(), + Settings.System.LOCK_TO_APP_ENABLED, 0) != 0) { + root.findPreference(KEY_SCREEN_PINNING).setSummary( + getResources().getString(R.string.switch_on_text)); + } - // Append the rest of the settings - addPreferencesFromResource(R.xml.security_settings_misc); + // SMS rate limit security check + boolean isTelephony = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); + if (isTelephony) { + mSmsSecurityCheck = (ListPreference) root.findPreference(KEY_SMS_SECURITY_CHECK_PREF); + mSmsSecurityCheck.setOnPreferenceChangeListener(this); + int smsSecurityCheck = Integer.valueOf(mSmsSecurityCheck.getValue()); + updateSmsSecuritySummary(smsSecurityCheck); + } - // Do not display SIM lock for devices without an Icc card - TelephonyManager tm = TelephonyManager.getDefault(); - CarrierConfigManager cfgMgr = (CarrierConfigManager) - getActivity().getSystemService(Context.CARRIER_CONFIG_SERVICE); - PersistableBundle b = cfgMgr.getConfig(); - if (!mIsPrimary || !isSimIccReady() || - b.getBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL)) { - root.removePreference(root.findPreference(KEY_SIM_LOCK)); - } else { - // Disable SIM lock if there is no ready SIM card. - root.findPreference(KEY_SIM_LOCK).setEnabled(isSimReady()); - } - if (Settings.System.getInt(getContentResolver(), - Settings.System.LOCK_TO_APP_ENABLED, 0) != 0) { - root.findPreference(KEY_SCREEN_PINNING).setSummary( - getResources().getString(R.string.switch_on_text)); - } + // Show password + mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD); + mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS); - // SMS rate limit security check - boolean isTelephony = pm.hasSystemFeature(PackageManager.FEATURE_TELEPHONY); - if (isTelephony) { - mSmsSecurityCheck = (ListPreference) root.findPreference(KEY_SMS_SECURITY_CHECK_PREF); - mSmsSecurityCheck.setOnPreferenceChangeListener(this); - int smsSecurityCheck = Integer.valueOf(mSmsSecurityCheck.getValue()); - updateSmsSecuritySummary(smsSecurityCheck); - } + // Credential storage + final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); + mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume() + if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { + Preference credentialStorageType = root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE); - // Show password - mShowPassword = (SwitchPreference) root.findPreference(KEY_SHOW_PASSWORD); - mResetCredentials = root.findPreference(KEY_RESET_CREDENTIALS); + final int storageSummaryRes = + mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware + : R.string.credential_storage_type_software; + credentialStorageType.setSummary(storageSummaryRes); + } else { + PreferenceGroup credentialsManager = (PreferenceGroup) + root.findPreference(KEY_CREDENTIALS_MANAGER); + credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS)); + credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL)); + credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE)); + } - // Credential storage - final UserManager um = (UserManager) getActivity().getSystemService(Context.USER_SERVICE); - mKeyStore = KeyStore.getInstance(); // needs to be initialized for onResume() - if (!um.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { - Preference credentialStorageType = root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE); - - final int storageSummaryRes = - mKeyStore.isHardwareBacked() ? R.string.credential_storage_type_hardware - : R.string.credential_storage_type_software; - credentialStorageType.setSummary(storageSummaryRes); - } else { - PreferenceGroup credentialsManager = (PreferenceGroup) - root.findPreference(KEY_CREDENTIALS_MANAGER); - credentialsManager.removePreference(root.findPreference(KEY_RESET_CREDENTIALS)); - credentialsManager.removePreference(root.findPreference(KEY_CREDENTIALS_INSTALL)); - credentialsManager.removePreference(root.findPreference(KEY_CREDENTIAL_STORAGE_TYPE)); - } - - // Application install - PreferenceGroup deviceAdminCategory = (PreferenceGroup) - root.findPreference(KEY_DEVICE_ADMIN_CATEGORY); - mToggleAppInstallation = (SwitchPreference) findPreference( - KEY_TOGGLE_INSTALL_APPLICATIONS); - mToggleAppInstallation.setChecked(isNonMarketAppsAllowed()); - // Side loading of apps. - // Disable for restricted profiles. For others, check if policy disallows it. - mToggleAppInstallation.setEnabled(!um.getUserInfo(MY_USER_ID).isRestricted()); - if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) - || um.hasUserRestriction(UserManager.DISALLOW_INSTALL_APPS)) { - mToggleAppInstallation.setEnabled(false); - } - - // Advanced Security features - PreferenceGroup advancedCategory = - (PreferenceGroup)root.findPreference(KEY_ADVANCED_SECURITY); - if (advancedCategory != null) { - Preference manageAgents = advancedCategory.findPreference(KEY_MANAGE_TRUST_AGENTS); - if (manageAgents != null && !mLockPatternUtils.isSecure(MY_USER_ID)) { - manageAgents.setEnabled(false); - manageAgents.setSummary(R.string.disabled_because_no_backup_security); - } - } - - // The above preferences come and go based on security state, so we need to update - // the index. This call is expected to be fairly cheap, but we may want to do something - // smarter in the future. - Index.getInstance(getActivity()) - .updateFromClassNameResource(SecuritySettings.class.getName(), true, true); + // Application install + PreferenceGroup deviceAdminCategory = (PreferenceGroup) + root.findPreference(KEY_DEVICE_ADMIN_CATEGORY); + mToggleAppInstallation = (SwitchPreference) findPreference( + KEY_TOGGLE_INSTALL_APPLICATIONS); + mToggleAppInstallation.setChecked(isNonMarketAppsAllowed()); + // Side loading of apps. + // Disable for restricted profiles. For others, check if policy disallows it. + mToggleAppInstallation.setEnabled(!um.getUserInfo(MY_USER_ID).isRestricted()); + if (um.hasUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES) + || um.hasUserRestriction(UserManager.DISALLOW_INSTALL_APPS)) { + mToggleAppInstallation.setEnabled(false); + } + // Advanced Security features + PreferenceGroup advancedCategory = + (PreferenceGroup)root.findPreference(KEY_ADVANCED_SECURITY); + if (advancedCategory != null) { + Preference manageAgents = advancedCategory.findPreference(KEY_MANAGE_TRUST_AGENTS); + if (manageAgents != null && !mLockPatternUtils.isSecure(MY_USER_ID)) { + manageAgents.setEnabled(false); + manageAgents.setSummary(R.string.disabled_because_no_backup_security); + } + } + + // The above preferences come and go based on security state, so we need to update + // the index. This call is expected to be fairly cheap, but we may want to do something + // smarter in the future. + Index.getInstance(getActivity()) + .updateFromClassNameResource(SecuritySettings.class.getName(), true, true); + } for (int i = 0; i < SWITCH_PREFERENCE_KEYS.length; i++) { final Preference pref = findPreference(SWITCH_PREFERENCE_KEYS[i]); if (pref != null) pref.setOnPreferenceChangeListener(this); diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java index 380d24f..53cdbaa 100644 --- a/src/com/android/settings/Settings.java +++ b/src/com/android/settings/Settings.java @@ -123,4 +123,6 @@ public class Settings extends SettingsActivity { public static class BlacklistSettingsActivity extends SettingsActivity { /* empty */ } public static class AnonymousStatsActivity extends Settings { /* empty */ } public static class ContributorsCloudActivity extends SettingsActivity { /* empty */ } -} \ No newline at end of file + public static class SoundSettingsActivity 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 9dc5021..9670139 100644 --- a/src/com/android/settings/SettingsActivity.java +++ b/src/com/android/settings/SettingsActivity.java @@ -95,7 +95,9 @@ import com.android.settings.deviceinfo.StorageSettings; import com.android.settings.fuelgauge.PowerUsageDetail; import com.android.settings.fuelgauge.PowerUsageSummary; import com.android.settings.livedisplay.LiveDisplay; +import com.android.settings.notification.NotificationManagerSettings; import com.android.settings.notification.OtherSoundSettings; +import com.android.settings.notification.SoundSettings; import com.android.settings.profiles.NFCProfileTagCallback; import com.android.settings.search.DynamicIndexableContentMonitor; import com.android.settings.search.Index; @@ -108,7 +110,6 @@ import com.android.settings.nfc.AndroidBeam; import com.android.settings.nfc.PaymentSettings; import com.android.settings.notification.AppNotificationSettings; import com.android.settings.notification.NotificationAccessSettings; -import com.android.settings.notification.NotificationSettings; import com.android.settings.notification.NotificationStation; import com.android.settings.notification.OtherSoundSettings; import com.android.settings.notification.ZenAccessSettings; @@ -271,8 +272,10 @@ public class SettingsActivity extends Activity R.id.sim_settings, R.id.wireless_settings, R.id.device_section, - R.id.notification_settings, - R.id.display_settings, + R.id.sound_settings, + R.id.display_and_lights_settings, + R.id.lockscreen_settings, + R.id.notification_manager, R.id.storage_settings, R.id.application_settings, R.id.battery_settings, @@ -287,7 +290,6 @@ public class SettingsActivity extends Activity R.id.about_settings, R.id.accessibility_settings, R.id.print_settings, - R.id.nfc_payment_settings, R.id.home_settings, R.id.dashboard, R.id.privacy_settings_cyanogenmod @@ -347,7 +349,7 @@ public class SettingsActivity extends Activity PaymentSettings.class.getName(), KeyboardLayoutPickerFragment.class.getName(), ZenModeSettings.class.getName(), - NotificationSettings.class.getName(), + SoundSettings.class.getName(), ChooseLockPassword.ChooseLockPasswordFragment.class.getName(), ChooseLockPattern.ChooseLockPatternFragment.class.getName(), InstalledAppDetails.class.getName(), @@ -369,7 +371,8 @@ public class SettingsActivity extends Activity com.android.settings.cyanogenmod.DisplayRotation.class.getName(), com.android.settings.cyanogenmod.PrivacySettings.class.getName(), BlacklistSettings.class.getName(), - ContributorsCloudFragment.class.getName() + ContributorsCloudFragment.class.getName(), + NotificationManagerSettings.class.getName() }; @@ -1297,18 +1300,6 @@ public class SettingsActivity extends Activity || Utils.isMonkeyRunning()) { removeTile = true; } - } else if (id == R.id.nfc_payment_settings) { - if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) { - removeTile = true; - } else { - // Only show if NFC is on and we have the HCE feature - NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this); - if (adapter == null || !adapter.isEnabled() || - !getPackageManager().hasSystemFeature( - PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) { - removeTile = true; - } - } } else if (id == R.id.print_settings) { boolean hasPrintingSupport = getPackageManager().hasSystemFeature( PackageManager.FEATURE_PRINTING); @@ -1563,4 +1554,4 @@ public class SettingsActivity extends Activity super.onNewIntent(intent); } -} \ No newline at end of file +} diff --git a/src/com/android/settings/WirelessSettings.java b/src/com/android/settings/WirelessSettings.java index df430ef..a5cbf9e 100644 --- a/src/com/android/settings/WirelessSettings.java +++ b/src/com/android/settings/WirelessSettings.java @@ -74,6 +74,7 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde private static final String KEY_TOGGLE_NSD = "toggle_nsd"; //network service discovery private static final String KEY_CELL_BROADCAST_SETTINGS = "cell_broadcast_settings"; private static final String KEY_WFC_SETTINGS = "wifi_calling_settings"; + private static final String KEY_NFC_PAYMENT_SETTINGS = "nfc_payment_settings"; public static final String EXIT_ECM_RESULT = "exit_ecm_result"; public static final int REQUEST_CODE_EXIT_ECM = 1; @@ -290,6 +291,7 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde mNfcAdapter = NfcAdapter.getDefaultAdapter(activity); if (mNfcAdapter == null) { getPreferenceScreen().removePreference(nfcCategory); + removePreference(KEY_NFC_PAYMENT_SETTINGS); mNfcEnabler = null; } @@ -299,12 +301,13 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde || mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS)) { removePreference(KEY_MOBILE_NETWORK_SETTINGS); removePreference(KEY_MANAGE_MOBILE_PLAN); + removePreference(KEY_NFC_PAYMENT_SETTINGS); } // Remove Mobile Network Settings and Manage Mobile Plan // if config_show_mobile_plan sets false. final boolean isMobilePlanEnabled = this.getResources().getBoolean( R.bool.config_show_mobile_plan); - if (!isMobilePlanEnabled) { + if (!isMobilePlanEnabled || mCm.getMobileProvisioningUrl().isEmpty()) { Preference pref = findPreference(KEY_MANAGE_MOBILE_PLAN); if (pref != null) { removePreference(KEY_MANAGE_MOBILE_PLAN); @@ -473,11 +476,14 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde result.add(KEY_MANAGE_MOBILE_PLAN); } + ConnectivityManager cm = (ConnectivityManager) + context.getSystemService(Context.CONNECTIVITY_SERVICE); + // Remove Mobile Network Settings and Manage Mobile Plan // if config_show_mobile_plan sets false. final boolean isMobilePlanEnabled = context.getResources().getBoolean( R.bool.config_show_mobile_plan); - if (!isMobilePlanEnabled) { + if (!isMobilePlanEnabled || cm.getMobileProvisioningUrl().isEmpty()) { result.add(KEY_MANAGE_MOBILE_PLAN); } @@ -492,8 +498,6 @@ public class WirelessSettings extends SettingsPreferenceFragment implements Inde result.add(KEY_PROXY_SETTINGS); // Disable Tethering if it's not allowed or if it's a wifi-only device - ConnectivityManager cm = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); if (isSecondaryUser || !cm.isTetheringSupported()) { result.add(KEY_TETHER_SETTINGS); } diff --git a/src/com/android/settings/cyanogenmod/DisplayRotation.java b/src/com/android/settings/cyanogenmod/DisplayRotation.java index 67fa571..122e836 100644 --- a/src/com/android/settings/cyanogenmod/DisplayRotation.java +++ b/src/com/android/settings/cyanogenmod/DisplayRotation.java @@ -35,7 +35,7 @@ import com.android.internal.logging.MetricsLogger; public class DisplayRotation extends SettingsPreferenceFragment { private static final String TAG = "DisplayRotation"; - private static final String KEY_ACCELEROMETER = "accelerometer"; + public static final String KEY_ACCELEROMETER = "accelerometer"; private static final String KEY_LOCKSCREEN_ROTATION = "lockscreen_rotation"; private static final String ROTATION_0_PREF = "display_rotation_0"; private static final String ROTATION_90_PREF = "display_rotation_90"; diff --git a/src/com/android/settings/notification/NotificationManagerSettings.java b/src/com/android/settings/notification/NotificationManagerSettings.java new file mode 100644 index 0000000..d25d186 --- /dev/null +++ b/src/com/android/settings/notification/NotificationManagerSettings.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2015 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.notification; + +import android.content.Context; +import android.os.Bundle; +import android.os.UserHandle; +import android.preference.PreferenceCategory; +import android.provider.SearchIndexableResource; +import android.provider.Settings; +import android.util.Log; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.widget.LockPatternUtils; +import com.android.settings.DropDownPreference; +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; + +import java.util.ArrayList; +import java.util.List; + +public class NotificationManagerSettings extends SettingsPreferenceFragment + implements Indexable { + + private static final String TAG = NotificationManagerSettings.class.getSimpleName(); + + private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "lock_screen_notifications"; + + private boolean mSecure; + private int mLockscreenSelectedValue; + private DropDownPreference mLockscreen; + + @Override + public void onCreate(Bundle icicle) { + super.onCreate(icicle); + addPreferencesFromResource(R.xml.notification_manager_settings); + mSecure = new LockPatternUtils(getActivity()).isSecure(UserHandle.myUserId()); + initLockscreenNotifications(); + } + + // === Lockscreen (public / private) notifications === + + private void initLockscreenNotifications() { + mLockscreen = (DropDownPreference) findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS); + if (mLockscreen == null) { + Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS); + return; + } + + mLockscreen.addItem(R.string.lock_screen_notifications_summary_show, + R.string.lock_screen_notifications_summary_show); + if (mSecure) { + mLockscreen.addItem(R.string.lock_screen_notifications_summary_hide, + R.string.lock_screen_notifications_summary_hide); + } + mLockscreen.addItem(R.string.lock_screen_notifications_summary_disable, + R.string.lock_screen_notifications_summary_disable); + updateLockscreenNotifications(); + mLockscreen.setCallback(new DropDownPreference.Callback() { + @Override + public boolean onItemSelected(int pos, Object value) { + final int val = (Integer) value; + if (val == mLockscreenSelectedValue) { + return true; + } + final boolean enabled = val != R.string.lock_screen_notifications_summary_disable; + final boolean show = val == R.string.lock_screen_notifications_summary_show; + Settings.Secure.putInt(getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0); + Settings.Secure.putInt(getContentResolver(), + Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0); + mLockscreenSelectedValue = val; + return true; + } + }); + } + + private void updateLockscreenNotifications() { + if (mLockscreen == null) { + return; + } + final boolean enabled = getLockscreenNotificationsEnabled(); + final boolean allowPrivate = !mSecure || getLockscreenAllowPrivateNotifications(); + mLockscreenSelectedValue = !enabled ? R.string.lock_screen_notifications_summary_disable : + allowPrivate ? R.string.lock_screen_notifications_summary_show : + R.string.lock_screen_notifications_summary_hide; + mLockscreen.setSelectedValue(mLockscreenSelectedValue); + } + + private boolean getLockscreenNotificationsEnabled() { + return Settings.Secure.getInt(getContentResolver(), + Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0; + } + + private boolean getLockscreenAllowPrivateNotifications() { + return Settings.Secure.getInt(getContentResolver(), + Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0; + } + + public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + @Override + public List getXmlResourcesToIndex(Context context, + boolean enabled) { + ArrayList result = + new ArrayList(); + + SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.notification_manager_settings; + result.add(sir); + + return result; + } + }; + + @Override + protected int getMetricsCategory() { + return MetricsLogger.DONT_TRACK_ME_BRO; + } +} diff --git a/src/com/android/settings/notification/NotificationSettings.java b/src/com/android/settings/notification/NotificationSettings.java deleted file mode 100644 index df4305d..0000000 --- a/src/com/android/settings/notification/NotificationSettings.java +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Copyright (C) 2014 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.notification; - -import android.app.NotificationManager; -import android.app.admin.DevicePolicyManager; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.pm.PackageManager; -import android.content.pm.ServiceInfo; -import android.database.ContentObserver; -import android.database.Cursor; -import android.database.sqlite.SQLiteException; -import android.media.AudioManager; -import android.media.RingtoneManager; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import android.os.Message; -import android.os.UserHandle; -import android.os.UserManager; -import android.os.Vibrator; -import android.preference.Preference; -import android.preference.Preference.OnPreferenceChangeListener; -import android.preference.PreferenceCategory; -import android.preference.SeekBarVolumizer; -import android.preference.TwoStatePreference; -import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.provider.SearchIndexableResource; -import android.provider.Settings; -import android.util.Log; - -import com.android.internal.logging.MetricsLogger; -import com.android.internal.widget.LockPatternUtils; -import com.android.settings.DropDownPreference; -import com.android.settings.R; -import com.android.settings.SettingsPreferenceFragment; -import com.android.settings.Utils; -import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settings.search.Indexable; -import cyanogenmod.providers.CMSettings; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -public class NotificationSettings extends SettingsPreferenceFragment implements Indexable { - private static final String TAG = "NotificationSettings"; - - private static final String KEY_SOUND = "sound"; - private static final String KEY_MEDIA_VOLUME = "media_volume"; - private static final String KEY_ALARM_VOLUME = "alarm_volume"; - private static final String KEY_RING_VOLUME = "ring_volume"; - private static final String KEY_NOTIFICATION_VOLUME = "notification_volume"; - private static final String KEY_PHONE_RINGTONE = "ringtone"; - private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone"; - private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing"; - private static final String KEY_WIFI_DISPLAY = "wifi_display"; - private static final String KEY_NOTIFICATION = "notification"; - private static final String KEY_NOTIFICATION_PULSE = "notification_pulse"; - private static final String KEY_LOCK_SCREEN_NOTIFICATIONS = "lock_screen_notifications"; - private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access"; - private static final String KEY_INCREASING_RING_VOLUME = "increasing_ring_volume"; - private static final String KEY_NOTIFICATION_LIGHT = "notification_light"; - private static final String KEY_BATTERY_LIGHT = "battery_light"; - private static final String KEY_ZEN_ACCESS = "manage_zen_access"; - private static final String KEY_ZEN_MODE = "zen_mode"; - - private static final String[] RESTRICTED_KEYS = { - KEY_MEDIA_VOLUME, - KEY_ALARM_VOLUME, - KEY_RING_VOLUME, - KEY_NOTIFICATION_VOLUME, - KEY_ZEN_ACCESS, - KEY_ZEN_MODE, - }; - - private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds - - private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback(); - private final IncreasingRingVolumePreference.Callback mIncreasingRingVolumeCallback = - new IncreasingRingVolumePreference.Callback() { - @Override - public void onStartingSample() { - mVolumeCallback.stopSample(); - } - }; - - private final H mHandler = new H(); - private final SettingsObserver mSettingsObserver = new SettingsObserver(); - private final Receiver mReceiver = new Receiver(); - private final ArrayList mVolumePrefs = new ArrayList<>(); - - private Context mContext; - private PackageManager mPM; - private boolean mVoiceCapable; - private Vibrator mVibrator; - private AudioManager mAudioManager; - private VolumeSeekBarPreference mRingOrNotificationPreference; - - private TwoStatePreference mIncreasingRing; - private IncreasingRingVolumePreference mIncreasingRingVolume; - private Preference mPhoneRingtonePreference; - private Preference mNotificationRingtonePreference; - private TwoStatePreference mVibrateWhenRinging; - private TwoStatePreference mNotificationPulse; - private DropDownPreference mLockscreen; - private Preference mNotificationAccess; - private Preference mZenAccess; - private boolean mSecure; - private int mLockscreenSelectedValue; - private ComponentName mSuppressor; - private int mRingerMode = -1; - - private UserManager mUserManager; - - @Override - protected int getMetricsCategory() { - return MetricsLogger.NOTIFICATION; - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mContext = getActivity(); - mPM = mContext.getPackageManager(); - mUserManager = UserManager.get(getContext()); - mVoiceCapable = Utils.isVoiceCapable(mContext); - mSecure = new LockPatternUtils(getActivity()).isSecure(UserHandle.myUserId()); - - mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); - mVibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE); - if (mVibrator != null && !mVibrator.hasVibrator()) { - mVibrator = null; - } - - addPreferencesFromResource(R.xml.notification_settings); - - final PreferenceCategory sound = (PreferenceCategory) findPreference(KEY_SOUND); - initVolumePreference(KEY_MEDIA_VOLUME, AudioManager.STREAM_MUSIC, - com.android.internal.R.drawable.ic_audio_media_mute); - initVolumePreference(KEY_ALARM_VOLUME, AudioManager.STREAM_ALARM, - com.android.internal.R.drawable.ic_audio_alarm_mute); - if (mVoiceCapable) { - mRingOrNotificationPreference = - initVolumePreference(KEY_RING_VOLUME, AudioManager.STREAM_RING, - com.android.internal.R.drawable.ic_audio_ring_notif_mute); - sound.removePreference(sound.findPreference(KEY_NOTIFICATION_VOLUME)); - } else { - mRingOrNotificationPreference = - initVolumePreference(KEY_NOTIFICATION_VOLUME, AudioManager.STREAM_NOTIFICATION, - com.android.internal.R.drawable.ic_audio_ring_notif_mute); - sound.removePreference(sound.findPreference(KEY_RING_VOLUME)); - } - initRingtones(sound); - initVibrateWhenRinging(sound); - initIncreasingRing(sound); - - final PreferenceCategory notification = (PreferenceCategory) - findPreference(KEY_NOTIFICATION); - initPulse(notification); - initLockscreenNotifications(notification); - - mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS); - refreshNotificationListeners(); - mZenAccess = findPreference(KEY_ZEN_ACCESS); - refreshZenAccess(); - updateRingerMode(); - updateEffectsSuppressor(); - } - - @Override - public void onResume() { - super.onResume(); - refreshNotificationListeners(); - refreshZenAccess(); - lookupRingtoneNames(); - mSettingsObserver.register(true); - mReceiver.register(true); - updateRingOrNotificationPreference(); - updateEffectsSuppressor(); - for (VolumeSeekBarPreference volumePref : mVolumePrefs) { - volumePref.onActivityResume(); - } - boolean isRestricted = mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME); - for (String key : RESTRICTED_KEYS) { - Preference pref = findPreference(key); - if (pref != null) { - pref.setEnabled(!isRestricted); - } - } - } - - @Override - public void onPause() { - super.onPause(); - mVolumeCallback.stopSample(); - mSettingsObserver.register(false); - mReceiver.register(false); - } - - // === Volumes === - - private VolumeSeekBarPreference initVolumePreference(String key, int stream, int muteIcon) { - final VolumeSeekBarPreference volumePref = (VolumeSeekBarPreference) findPreference(key); - volumePref.setCallback(mVolumeCallback); - volumePref.setStream(stream); - mVolumePrefs.add(volumePref); - volumePref.setMuteIcon(muteIcon); - return volumePref; - } - - private void updateRingOrNotificationPreference() { - mRingOrNotificationPreference.showIcon(mSuppressor != null - ? com.android.internal.R.drawable.ic_audio_ring_notif_mute - : mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate() - ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate - : com.android.internal.R.drawable.ic_audio_ring_notif); - } - - private boolean wasRingerModeVibrate() { - return mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_SILENT - && mAudioManager.getLastAudibleStreamVolume(AudioManager.STREAM_RING) == 0; - } - - private void updateRingerMode() { - final int ringerMode = mAudioManager.getRingerModeInternal(); - if (mRingerMode == ringerMode) return; - mRingerMode = ringerMode; - updateRingOrNotificationPreference(); - } - - private void updateEffectsSuppressor() { - final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor(); - if (Objects.equals(suppressor, mSuppressor)) return; - mSuppressor = suppressor; - if (mRingOrNotificationPreference != null) { - final String text = suppressor != null ? - mContext.getString(com.android.internal.R.string.muted_by, - getSuppressorCaption(suppressor)) : null; - mRingOrNotificationPreference.setSuppressionText(text); - } - updateRingOrNotificationPreference(); - } - - private String getSuppressorCaption(ComponentName suppressor) { - final PackageManager pm = mContext.getPackageManager(); - try { - final ServiceInfo info = pm.getServiceInfo(suppressor, 0); - if (info != null) { - final CharSequence seq = info.loadLabel(pm); - if (seq != null) { - final String str = seq.toString().trim(); - if (str.length() > 0) { - return str; - } - } - } - } catch (Throwable e) { - Log.w(TAG, "Error loading suppressor caption", e); - } - return suppressor.getPackageName(); - } - - private final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback { - private SeekBarVolumizer mCurrent; - - @Override - public void onSampleStarting(SeekBarVolumizer sbv) { - if (mCurrent != null && mCurrent != sbv) { - mCurrent.stopSample(); - } - if (mIncreasingRingVolume != null) { - mIncreasingRingVolume.stopSample(); - } - mCurrent = sbv; - if (mCurrent != null) { - mHandler.removeMessages(H.STOP_SAMPLE); - mHandler.sendEmptyMessageDelayed(H.STOP_SAMPLE, SAMPLE_CUTOFF); - } - } - - @Override - public void onStreamValueChanged(int stream, int progress) { - // noop - } - - public void stopSample() { - if (mCurrent != null) { - mCurrent.stopSample(); - } - } - }; - - - // === Phone & notification ringtone === - - private void initRingtones(PreferenceCategory root) { - mPhoneRingtonePreference = root.findPreference(KEY_PHONE_RINGTONE); - if (mPhoneRingtonePreference != null && !mVoiceCapable) { - root.removePreference(mPhoneRingtonePreference); - mPhoneRingtonePreference = null; - } - mNotificationRingtonePreference = root.findPreference(KEY_NOTIFICATION_RINGTONE); - } - - private void lookupRingtoneNames() { - AsyncTask.execute(mLookupRingtoneNames); - } - - private final Runnable mLookupRingtoneNames = new Runnable() { - @Override - public void run() { - if (mPhoneRingtonePreference != null) { - final CharSequence summary = updateRingtoneName( - mContext, RingtoneManager.TYPE_RINGTONE); - if (summary != null) { - mHandler.obtainMessage(H.UPDATE_PHONE_RINGTONE, summary).sendToTarget(); - } - } - if (mNotificationRingtonePreference != null) { - final CharSequence summary = updateRingtoneName( - mContext, RingtoneManager.TYPE_NOTIFICATION); - if (summary != null) { - mHandler.obtainMessage(H.UPDATE_NOTIFICATION_RINGTONE, summary).sendToTarget(); - } - } - } - }; - - private static CharSequence updateRingtoneName(Context context, int type) { - if (context == null) { - Log.e(TAG, "Unable to update ringtone name, no context provided"); - return null; - } - Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type); - CharSequence summary = context.getString(com.android.internal.R.string.ringtone_unknown); - // Is it a silent ringtone? - if (ringtoneUri == null) { - summary = context.getString(com.android.internal.R.string.ringtone_silent); - } else { - Cursor cursor = null; - try { - if (MediaStore.AUTHORITY.equals(ringtoneUri.getAuthority())) { - // Fetch the ringtone title from the media provider - cursor = context.getContentResolver().query(ringtoneUri, - new String[] { MediaStore.Audio.Media.TITLE }, null, null, null); - } else if (ContentResolver.SCHEME_CONTENT.equals(ringtoneUri.getScheme())) { - cursor = context.getContentResolver().query(ringtoneUri, - new String[] { OpenableColumns.DISPLAY_NAME }, null, null, null); - } - if (cursor != null) { - if (cursor.moveToFirst()) { - summary = cursor.getString(0); - } - } - } catch (SQLiteException sqle) { - // Unknown title for the ringtone - } catch (IllegalArgumentException iae) { - // Some other error retrieving the column from the provider - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - return summary; - } - - // === Increasing ringtone === - - private void initIncreasingRing(PreferenceCategory root) { - mIncreasingRing = (TwoStatePreference) - root.findPreference(CMSettings.System.INCREASING_RING); - mIncreasingRingVolume = (IncreasingRingVolumePreference) - root.findPreference(KEY_INCREASING_RING_VOLUME); - - if (mIncreasingRing == null || mIncreasingRingVolume == null || !mVoiceCapable) { - if (mIncreasingRing != null) { - root.removePreference(mIncreasingRing); - mIncreasingRing = null; - } - if (mIncreasingRingVolume != null) { - root.removePreference(mIncreasingRingVolume); - mIncreasingRingVolume = null; - } - } else { - mIncreasingRingVolume.setCallback(mIncreasingRingVolumeCallback); - } - } - - // === Vibrate when ringing === - - private void initVibrateWhenRinging(PreferenceCategory root) { - mVibrateWhenRinging = (TwoStatePreference) root.findPreference(KEY_VIBRATE_WHEN_RINGING); - if (mVibrateWhenRinging == null) { - Log.i(TAG, "Preference not found: " + KEY_VIBRATE_WHEN_RINGING); - return; - } - if (!mVoiceCapable) { - root.removePreference(mVibrateWhenRinging); - mVibrateWhenRinging = null; - return; - } - mVibrateWhenRinging.setPersistent(false); - updateVibrateWhenRinging(); - mVibrateWhenRinging.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { - @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean val = (Boolean) newValue; - return Settings.System.putInt(getContentResolver(), - Settings.System.VIBRATE_WHEN_RINGING, - val ? 1 : 0); - } - }); - } - - private void updateVibrateWhenRinging() { - if (mVibrateWhenRinging == null) return; - mVibrateWhenRinging.setChecked(Settings.System.getInt(getContentResolver(), - Settings.System.VIBRATE_WHEN_RINGING, 0) != 0); - } - - // === Pulse notification light === - - private void initPulse(PreferenceCategory parent) { - if (!getResources().getBoolean( - com.android.internal.R.bool.config_intrusiveNotificationLed)) { - parent.removePreference(parent.findPreference(KEY_NOTIFICATION_LIGHT)); - } - if (!getResources().getBoolean( - com.android.internal.R.bool.config_intrusiveBatteryLed) - || UserHandle.myUserId() != UserHandle.USER_OWNER) { - parent.removePreference(parent.findPreference(KEY_BATTERY_LIGHT)); - } - } - - private void updatePulse() { - if (mNotificationPulse == null) { - return; - } - try { - mNotificationPulse.setChecked(Settings.System.getInt(getContentResolver(), - Settings.System.NOTIFICATION_LIGHT_PULSE) == 1); - } catch (Settings.SettingNotFoundException snfe) { - Log.e(TAG, Settings.System.NOTIFICATION_LIGHT_PULSE + " not found"); - } - } - - // === Lockscreen (public / private) notifications === - - private void initLockscreenNotifications(PreferenceCategory parent) { - mLockscreen = (DropDownPreference) parent.findPreference(KEY_LOCK_SCREEN_NOTIFICATIONS); - if (mLockscreen == null) { - Log.i(TAG, "Preference not found: " + KEY_LOCK_SCREEN_NOTIFICATIONS); - return; - } - - boolean isSecureNotificationsDisabled = isSecureNotificationsDisabled(); - boolean isUnredactedNotificationsDisabled = isUnredactedNotificationsDisabled(); - if (!isSecureNotificationsDisabled && !isUnredactedNotificationsDisabled) { - mLockscreen.addItem(R.string.lock_screen_notifications_summary_show, - R.string.lock_screen_notifications_summary_show); - } - if (mSecure && !isSecureNotificationsDisabled) { - mLockscreen.addItem(R.string.lock_screen_notifications_summary_hide, - R.string.lock_screen_notifications_summary_hide); - } - mLockscreen.addItem(R.string.lock_screen_notifications_summary_disable, - R.string.lock_screen_notifications_summary_disable); - updateLockscreenNotifications(); - if (mLockscreen.getItemCount() > 1) { - mLockscreen.setCallback(new DropDownPreference.Callback() { - @Override - public boolean onItemSelected(int pos, Object value) { - final int val = (Integer) value; - if (val == mLockscreenSelectedValue) { - return true; - } - final boolean enabled = - val != R.string.lock_screen_notifications_summary_disable; - final boolean show = val == R.string.lock_screen_notifications_summary_show; - Settings.Secure.putInt(getContentResolver(), - Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, show ? 1 : 0); - Settings.Secure.putInt(getContentResolver(), - Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, enabled ? 1 : 0); - mLockscreenSelectedValue = val; - return true; - } - }); - } else { - // There is one or less option for the user, disable the drop down. - mLockscreen.setEnabled(false); - } - } - - private boolean isSecureNotificationsDisabled() { - final DevicePolicyManager dpm = - (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); - return dpm != null && (dpm.getKeyguardDisabledFeatures(null) - & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0; - } - - private boolean isUnredactedNotificationsDisabled() { - final DevicePolicyManager dpm = - (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); - return dpm != null && (dpm.getKeyguardDisabledFeatures(null) - & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0; - } - - private void updateLockscreenNotifications() { - if (mLockscreen == null) { - return; - } - final boolean enabled = getLockscreenNotificationsEnabled(); - final boolean allowPrivate = !mSecure || getLockscreenAllowPrivateNotifications(); - mLockscreenSelectedValue = !enabled ? R.string.lock_screen_notifications_summary_disable : - allowPrivate ? R.string.lock_screen_notifications_summary_show : - R.string.lock_screen_notifications_summary_hide; - mLockscreen.setSelectedValue(mLockscreenSelectedValue); - } - - private boolean getLockscreenNotificationsEnabled() { - return Settings.Secure.getInt(getContentResolver(), - Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) != 0; - } - - private boolean getLockscreenAllowPrivateNotifications() { - return Settings.Secure.getInt(getContentResolver(), - Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 0) != 0; - } - - // === Notification listeners === - - private void refreshNotificationListeners() { - if (mNotificationAccess != null) { - final int n = NotificationAccessSettings.getEnabledListenersCount(mContext); - if (n == 0) { - mNotificationAccess.setSummary(getResources().getString( - R.string.manage_notification_access_summary_zero)); - } else { - mNotificationAccess.setSummary(String.format(getResources().getQuantityString( - R.plurals.manage_notification_access_summary_nonzero, - n, n))); - } - } - } - - // === Zen access === - - private void refreshZenAccess() { - // noop for now - } - - // === Callbacks === - - private final class SettingsObserver extends ContentObserver { - private final Uri VIBRATE_WHEN_RINGING_URI = - Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING); - private final Uri NOTIFICATION_LIGHT_PULSE_URI = - Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE); - private final Uri LOCK_SCREEN_PRIVATE_URI = - Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); - private final Uri LOCK_SCREEN_SHOW_URI = - Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS); - - public SettingsObserver() { - super(mHandler); - } - - public void register(boolean register) { - final ContentResolver cr = getContentResolver(); - if (register) { - cr.registerContentObserver(VIBRATE_WHEN_RINGING_URI, false, this); - cr.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this); - cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this); - cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this); - } else { - cr.unregisterContentObserver(this); - } - } - - @Override - public void onChange(boolean selfChange, Uri uri) { - super.onChange(selfChange, uri); - if (VIBRATE_WHEN_RINGING_URI.equals(uri)) { - updateVibrateWhenRinging(); - } - if (NOTIFICATION_LIGHT_PULSE_URI.equals(uri)) { - updatePulse(); - } - if (LOCK_SCREEN_PRIVATE_URI.equals(uri) || LOCK_SCREEN_SHOW_URI.equals(uri)) { - updateLockscreenNotifications(); - } - } - } - - private final class H extends Handler { - private static final int UPDATE_PHONE_RINGTONE = 1; - private static final int UPDATE_NOTIFICATION_RINGTONE = 2; - private static final int STOP_SAMPLE = 3; - private static final int UPDATE_EFFECTS_SUPPRESSOR = 4; - private static final int UPDATE_RINGER_MODE = 5; - - private H() { - super(Looper.getMainLooper()); - } - - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case UPDATE_PHONE_RINGTONE: - mPhoneRingtonePreference.setSummary((CharSequence) msg.obj); - break; - case UPDATE_NOTIFICATION_RINGTONE: - mNotificationRingtonePreference.setSummary((CharSequence) msg.obj); - break; - case STOP_SAMPLE: - mVolumeCallback.stopSample(); - break; - case UPDATE_EFFECTS_SUPPRESSOR: - updateEffectsSuppressor(); - break; - case UPDATE_RINGER_MODE: - updateRingerMode(); - break; - } - } - } - - private class Receiver extends BroadcastReceiver { - private boolean mRegistered; - - public void register(boolean register) { - if (mRegistered == register) return; - if (register) { - final IntentFilter filter = new IntentFilter(); - filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED); - filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); - mContext.registerReceiver(this, filter); - } else { - mContext.unregisterReceiver(this); - } - mRegistered = register; - } - - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(action)) { - mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR); - } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { - mHandler.sendEmptyMessage(H.UPDATE_RINGER_MODE); - } - } - } - - // === Indexing === - - public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider() { - - public List getXmlResourcesToIndex( - Context context, boolean enabled) { - final SearchIndexableResource sir = new SearchIndexableResource(context); - sir.xmlResId = R.xml.notification_settings; - return Arrays.asList(sir); - } - - public List getNonIndexableKeys(Context context) { - final ArrayList rt = new ArrayList(); - if (Utils.isVoiceCapable(context)) { - rt.add(KEY_NOTIFICATION_VOLUME); - } else { - rt.add(KEY_RING_VOLUME); - rt.add(KEY_PHONE_RINGTONE); - rt.add(KEY_WIFI_DISPLAY); - rt.add(KEY_VIBRATE_WHEN_RINGING); - } - return rt; - } - }; -} diff --git a/src/com/android/settings/notification/SoundSettings.java b/src/com/android/settings/notification/SoundSettings.java new file mode 100644 index 0000000..f265bd3 --- /dev/null +++ b/src/com/android/settings/notification/SoundSettings.java @@ -0,0 +1,608 @@ +/* + * Copyright (C) 2014 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.notification; + +import android.app.NotificationManager; +import android.app.admin.DevicePolicyManager; +import android.content.BroadcastReceiver; +import android.content.ComponentName; +import android.content.ContentResolver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.content.pm.PackageManager; +import android.content.pm.ServiceInfo; +import android.database.ContentObserver; +import android.database.Cursor; +import android.database.sqlite.SQLiteException; +import android.media.AudioManager; +import android.media.RingtoneManager; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.os.Message; +import android.os.UserHandle; +import android.os.UserManager; +import android.os.Vibrator; +import android.preference.Preference; +import android.preference.Preference.OnPreferenceChangeListener; +import android.preference.PreferenceCategory; +import android.preference.SeekBarVolumizer; +import android.preference.SwitchPreference; +import android.preference.TwoStatePreference; +import android.provider.MediaStore; +import android.provider.OpenableColumns; +import android.provider.SearchIndexableResource; +import android.provider.Settings; +import android.util.Log; + +import com.android.internal.logging.MetricsLogger; +import com.android.internal.widget.LockPatternUtils; +import com.android.settings.DropDownPreference; +import com.android.settings.R; +import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.Utils; +import com.android.settings.hardware.VibratorIntensity; +import com.android.settings.search.BaseSearchIndexProvider; +import com.android.settings.search.Indexable; +import cyanogenmod.providers.CMSettings; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +public class SoundSettings extends SettingsPreferenceFragment implements Indexable { + private static final String TAG = SoundSettings.class.getSimpleName(); + + private static final String KEY_SOUND = "sounds"; + private static final String KEY_VOLUMES = "volumes"; + private static final String KEY_VIBRATE = "vibrate"; + private static final String KEY_MEDIA_VOLUME = "media_volume"; + private static final String KEY_ALARM_VOLUME = "alarm_volume"; + private static final String KEY_RING_VOLUME = "ring_volume"; + private static final String KEY_NOTIFICATION_VOLUME = "notification_volume"; + private static final String KEY_PHONE_RINGTONE = "ringtone"; + private static final String KEY_NOTIFICATION_RINGTONE = "notification_ringtone"; + private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing"; + private static final String KEY_WIFI_DISPLAY = "wifi_display"; + private static final String KEY_NOTIFICATION = "notification"; + private static final String KEY_NOTIFICATION_PULSE = "notification_pulse"; + private static final String KEY_NOTIFICATION_ACCESS = "manage_notification_access"; + private static final String KEY_INCREASING_RING_VOLUME = "increasing_ring_volume"; + private static final String KEY_VIBRATION_INTENSITY = "vibration_intensity"; + private static final String KEY_ZEN_ACCESS = "manage_zen_access"; + private static final String KEY_ZEN_MODE = "zen_mode"; + + private static final String[] RESTRICTED_KEYS = { + KEY_MEDIA_VOLUME, + KEY_ALARM_VOLUME, + KEY_RING_VOLUME, + KEY_NOTIFICATION_VOLUME, + KEY_ZEN_ACCESS, + KEY_ZEN_MODE, + }; + + private static final int SAMPLE_CUTOFF = 2000; // manually cap sample playback at 2 seconds + + private final VolumePreferenceCallback mVolumeCallback = new VolumePreferenceCallback(); + private final IncreasingRingVolumePreference.Callback mIncreasingRingVolumeCallback = + new IncreasingRingVolumePreference.Callback() { + @Override + public void onStartingSample() { + mVolumeCallback.stopSample(); + } + }; + + private final H mHandler = new H(); + private final SettingsObserver mSettingsObserver = new SettingsObserver(); + private final Receiver mReceiver = new Receiver(); + private final ArrayList mVolumePrefs = new ArrayList<>(); + + private Context mContext; + private PackageManager mPM; + private boolean mVoiceCapable; + private Vibrator mVibrator; + private AudioManager mAudioManager; + private VolumeSeekBarPreference mRingOrNotificationPreference; + + private TwoStatePreference mIncreasingRing; + private IncreasingRingVolumePreference mIncreasingRingVolume; + private Preference mPhoneRingtonePreference; + private Preference mNotificationRingtonePreference; + private TwoStatePreference mVibrateWhenRinging; + private Preference mNotificationAccess; + private Preference mZenAccess; + private boolean mSecure; + private int mLockscreenSelectedValue; + private ComponentName mSuppressor; + private int mRingerMode = -1; + + private UserManager mUserManager; + + @Override + protected int getMetricsCategory() { + return MetricsLogger.NOTIFICATION; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + mContext = getActivity(); + mPM = mContext.getPackageManager(); + mUserManager = UserManager.get(getContext()); + mVoiceCapable = Utils.isVoiceCapable(mContext); + + mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); + mVibrator = (Vibrator) getActivity().getSystemService(Context.VIBRATOR_SERVICE); + if (mVibrator != null && !mVibrator.hasVibrator()) { + mVibrator = null; + } + + addPreferencesFromResource(R.xml.sounds); + + final PreferenceCategory volumes = (PreferenceCategory) findPreference(KEY_VOLUMES); + final PreferenceCategory sounds = (PreferenceCategory) findPreference(KEY_SOUND); + final PreferenceCategory vibrate = (PreferenceCategory) findPreference(KEY_VIBRATE); + initVolumePreference(KEY_MEDIA_VOLUME, AudioManager.STREAM_MUSIC, + com.android.internal.R.drawable.ic_audio_media_mute); + initVolumePreference(KEY_ALARM_VOLUME, AudioManager.STREAM_ALARM, + com.android.internal.R.drawable.ic_audio_alarm_mute); + if (mVoiceCapable) { + mRingOrNotificationPreference = + initVolumePreference(KEY_RING_VOLUME, AudioManager.STREAM_RING, + com.android.internal.R.drawable.ic_audio_ring_notif_mute); + volumes.removePreference(volumes.findPreference(KEY_NOTIFICATION_VOLUME)); + } else { + mRingOrNotificationPreference = + initVolumePreference(KEY_NOTIFICATION_VOLUME, AudioManager.STREAM_NOTIFICATION, + com.android.internal.R.drawable.ic_audio_ring_notif_mute); + volumes.removePreference(volumes.findPreference(KEY_RING_VOLUME)); + } + + if (!VibratorIntensity.isSupported(mContext)) { + removePreference(KEY_VIBRATION_INTENSITY); + } + + initRingtones(sounds); + initIncreasingRing(sounds); + initVibrateWhenRinging(vibrate); + + mNotificationAccess = findPreference(KEY_NOTIFICATION_ACCESS); + refreshNotificationListeners(); + mZenAccess = findPreference(KEY_ZEN_ACCESS); + refreshZenAccess(); + updateRingerMode(); + updateEffectsSuppressor(); + } + + @Override + public void onResume() { + super.onResume(); + refreshNotificationListeners(); + refreshZenAccess(); + lookupRingtoneNames(); + mSettingsObserver.register(true); + mReceiver.register(true); + updateRingOrNotificationPreference(); + updateEffectsSuppressor(); + for (VolumeSeekBarPreference volumePref : mVolumePrefs) { + volumePref.onActivityResume(); + } + boolean isRestricted = mUserManager.hasUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME); + for (String key : RESTRICTED_KEYS) { + Preference pref = findPreference(key); + if (pref != null) { + pref.setEnabled(!isRestricted); + } + } + } + + @Override + public void onPause() { + super.onPause(); + mVolumeCallback.stopSample(); + mSettingsObserver.register(false); + mReceiver.register(false); + } + + // === Volumes === + + private VolumeSeekBarPreference initVolumePreference(String key, int stream, int muteIcon) { + final VolumeSeekBarPreference volumePref = (VolumeSeekBarPreference) findPreference(key); + if (volumePref == null) return null; + volumePref.setCallback(mVolumeCallback); + volumePref.setStream(stream); + mVolumePrefs.add(volumePref); + volumePref.setMuteIcon(muteIcon); + return volumePref; + } + + private void updateRingOrNotificationPreference() { + mRingOrNotificationPreference.showIcon(mSuppressor != null + ? com.android.internal.R.drawable.ic_audio_ring_notif_mute + : mRingerMode == AudioManager.RINGER_MODE_VIBRATE || wasRingerModeVibrate() + ? com.android.internal.R.drawable.ic_audio_ring_notif_vibrate + : com.android.internal.R.drawable.ic_audio_ring_notif); + } + + private boolean wasRingerModeVibrate() { + return mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_SILENT + && mAudioManager.getLastAudibleStreamVolume(AudioManager.STREAM_RING) == 0; + } + + private void updateRingerMode() { + final int ringerMode = mAudioManager.getRingerModeInternal(); + if (mRingerMode == ringerMode) return; + mRingerMode = ringerMode; + updateRingOrNotificationPreference(); + } + + private void updateEffectsSuppressor() { + final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor(); + if (Objects.equals(suppressor, mSuppressor)) return; + mSuppressor = suppressor; + if (mRingOrNotificationPreference != null) { + final String text = suppressor != null ? + mContext.getString(com.android.internal.R.string.muted_by, + getSuppressorCaption(suppressor)) : null; + mRingOrNotificationPreference.setSuppressionText(text); + } + updateRingOrNotificationPreference(); + } + + private String getSuppressorCaption(ComponentName suppressor) { + final PackageManager pm = mContext.getPackageManager(); + try { + final ServiceInfo info = pm.getServiceInfo(suppressor, 0); + if (info != null) { + final CharSequence seq = info.loadLabel(pm); + if (seq != null) { + final String str = seq.toString().trim(); + if (str.length() > 0) { + return str; + } + } + } + } catch (Throwable e) { + Log.w(TAG, "Error loading suppressor caption", e); + } + return suppressor.getPackageName(); + } + + private final class VolumePreferenceCallback implements VolumeSeekBarPreference.Callback { + private SeekBarVolumizer mCurrent; + + @Override + public void onSampleStarting(SeekBarVolumizer sbv) { + if (mCurrent != null && mCurrent != sbv) { + mCurrent.stopSample(); + } + if (mIncreasingRingVolume != null) { + mIncreasingRingVolume.stopSample(); + } + mCurrent = sbv; + if (mCurrent != null) { + mHandler.removeMessages(H.STOP_SAMPLE); + mHandler.sendEmptyMessageDelayed(H.STOP_SAMPLE, SAMPLE_CUTOFF); + } + } + + @Override + public void onStreamValueChanged(int stream, int progress) { + // noop + } + + public void stopSample() { + if (mCurrent != null) { + mCurrent.stopSample(); + } + } + }; + + + // === Phone & notification ringtone === + + private void initRingtones(PreferenceCategory root) { + mPhoneRingtonePreference = root.findPreference(KEY_PHONE_RINGTONE); + if (mPhoneRingtonePreference != null && !mVoiceCapable) { + root.removePreference(mPhoneRingtonePreference); + mPhoneRingtonePreference = null; + } + mNotificationRingtonePreference = root.findPreference(KEY_NOTIFICATION_RINGTONE); + } + + private void lookupRingtoneNames() { + AsyncTask.execute(mLookupRingtoneNames); + } + + private final Runnable mLookupRingtoneNames = new Runnable() { + @Override + public void run() { + if (mPhoneRingtonePreference != null) { + final CharSequence summary = updateRingtoneName( + mContext, RingtoneManager.TYPE_RINGTONE); + if (summary != null) { + mHandler.obtainMessage(H.UPDATE_PHONE_RINGTONE, summary).sendToTarget(); + } + } + if (mNotificationRingtonePreference != null) { + final CharSequence summary = updateRingtoneName( + mContext, RingtoneManager.TYPE_NOTIFICATION); + if (summary != null) { + mHandler.obtainMessage(H.UPDATE_NOTIFICATION_RINGTONE, summary).sendToTarget(); + } + } + } + }; + + private static CharSequence updateRingtoneName(Context context, int type) { + if (context == null) { + Log.e(TAG, "Unable to update ringtone name, no context provided"); + return null; + } + Uri ringtoneUri = RingtoneManager.getActualDefaultRingtoneUri(context, type); + CharSequence summary = context.getString(com.android.internal.R.string.ringtone_unknown); + // Is it a silent ringtone? + if (ringtoneUri == null) { + summary = context.getString(com.android.internal.R.string.ringtone_silent); + } else { + Cursor cursor = null; + try { + if (MediaStore.AUTHORITY.equals(ringtoneUri.getAuthority())) { + // Fetch the ringtone title from the media provider + cursor = context.getContentResolver().query(ringtoneUri, + new String[] { MediaStore.Audio.Media.TITLE }, null, null, null); + } else if (ContentResolver.SCHEME_CONTENT.equals(ringtoneUri.getScheme())) { + cursor = context.getContentResolver().query(ringtoneUri, + new String[] { OpenableColumns.DISPLAY_NAME }, null, null, null); + } + if (cursor != null) { + if (cursor.moveToFirst()) { + summary = cursor.getString(0); + } + } + } catch (SQLiteException sqle) { + // Unknown title for the ringtone + } catch (IllegalArgumentException iae) { + // Some other error retrieving the column from the provider + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + return summary; + } + + // === Increasing ringtone === + + private void initIncreasingRing(PreferenceCategory root) { + mIncreasingRing = (TwoStatePreference) + root.findPreference(CMSettings.System.INCREASING_RING); + mIncreasingRingVolume = (IncreasingRingVolumePreference) + root.findPreference(KEY_INCREASING_RING_VOLUME); + + if (!mVoiceCapable) { + if (mIncreasingRing != null) { + root.removePreference(mIncreasingRing); + mIncreasingRing = null; + } + if (mIncreasingRingVolume != null) { + root.removePreference(mIncreasingRingVolume); + mIncreasingRingVolume = null; + } + } else { + if (mIncreasingRingVolume != null) { + mIncreasingRingVolume.setCallback(mIncreasingRingVolumeCallback); + } + } + } + + // === Vibrate when ringing === + + private void initVibrateWhenRinging(PreferenceCategory root) { + mVibrateWhenRinging = (TwoStatePreference) root.findPreference(KEY_VIBRATE_WHEN_RINGING); + if (mVibrateWhenRinging == null) { + Log.i(TAG, "Preference not found: " + KEY_VIBRATE_WHEN_RINGING); + return; + } + if (!mVoiceCapable) { + root.removePreference(mVibrateWhenRinging); + mVibrateWhenRinging = null; + return; + } + mVibrateWhenRinging.setPersistent(false); + updateVibrateWhenRinging(); + mVibrateWhenRinging.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + final boolean val = (Boolean) newValue; + return Settings.System.putInt(getContentResolver(), + Settings.System.VIBRATE_WHEN_RINGING, + val ? 1 : 0); + } + }); + } + + private void updateVibrateWhenRinging() { + if (mVibrateWhenRinging == null) return; + mVibrateWhenRinging.setChecked(Settings.System.getInt(getContentResolver(), + Settings.System.VIBRATE_WHEN_RINGING, 0) != 0); + } + + private boolean isSecureNotificationsDisabled() { + final DevicePolicyManager dpm = + (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); + return dpm != null && (dpm.getKeyguardDisabledFeatures(null) + & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_NOTIFICATIONS) != 0; + } + + private boolean isUnredactedNotificationsDisabled() { + final DevicePolicyManager dpm = + (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE); + return dpm != null && (dpm.getKeyguardDisabledFeatures(null) + & DevicePolicyManager.KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS) != 0; + } + + // === Notification listeners === + + private void refreshNotificationListeners() { + if (mNotificationAccess != null) { + final int n = NotificationAccessSettings.getEnabledListenersCount(mContext); + if (n == 0) { + mNotificationAccess.setSummary(getResources().getString( + R.string.manage_notification_access_summary_zero)); + } else { + mNotificationAccess.setSummary(String.format(getResources().getQuantityString( + R.plurals.manage_notification_access_summary_nonzero, + n, n))); + } + } + } + + // === Zen access === + + private void refreshZenAccess() { + // noop for now + } + + // === Callbacks === + + private final class SettingsObserver extends ContentObserver { + private final Uri VIBRATE_WHEN_RINGING_URI = + Settings.System.getUriFor(Settings.System.VIBRATE_WHEN_RINGING); + private final Uri NOTIFICATION_LIGHT_PULSE_URI = + Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE); + private final Uri LOCK_SCREEN_PRIVATE_URI = + Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS); + private final Uri LOCK_SCREEN_SHOW_URI = + Settings.Secure.getUriFor(Settings.Secure.LOCK_SCREEN_SHOW_NOTIFICATIONS); + + public SettingsObserver() { + super(mHandler); + } + + public void register(boolean register) { + final ContentResolver cr = getContentResolver(); + if (register) { + cr.registerContentObserver(VIBRATE_WHEN_RINGING_URI, false, this); + cr.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI, false, this); + cr.registerContentObserver(LOCK_SCREEN_PRIVATE_URI, false, this); + cr.registerContentObserver(LOCK_SCREEN_SHOW_URI, false, this); + } else { + cr.unregisterContentObserver(this); + } + } + + @Override + public void onChange(boolean selfChange, Uri uri) { + super.onChange(selfChange, uri); + if (VIBRATE_WHEN_RINGING_URI.equals(uri)) { + updateVibrateWhenRinging(); + } + } + } + + private final class H extends Handler { + private static final int UPDATE_PHONE_RINGTONE = 1; + private static final int UPDATE_NOTIFICATION_RINGTONE = 2; + private static final int STOP_SAMPLE = 3; + private static final int UPDATE_EFFECTS_SUPPRESSOR = 4; + private static final int UPDATE_RINGER_MODE = 5; + + private H() { + super(Looper.getMainLooper()); + } + + @Override + public void handleMessage(Message msg) { + switch (msg.what) { + case UPDATE_PHONE_RINGTONE: + mPhoneRingtonePreference.setSummary((CharSequence) msg.obj); + break; + case UPDATE_NOTIFICATION_RINGTONE: + mNotificationRingtonePreference.setSummary((CharSequence) msg.obj); + break; + case STOP_SAMPLE: + mVolumeCallback.stopSample(); + break; + case UPDATE_EFFECTS_SUPPRESSOR: + updateEffectsSuppressor(); + break; + case UPDATE_RINGER_MODE: + updateRingerMode(); + break; + } + } + } + + private class Receiver extends BroadcastReceiver { + private boolean mRegistered; + + public void register(boolean register) { + if (mRegistered == register) return; + if (register) { + final IntentFilter filter = new IntentFilter(); + filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED); + filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION); + mContext.registerReceiver(this, filter); + } else { + mContext.unregisterReceiver(this); + } + mRegistered = register; + } + + @Override + public void onReceive(Context context, Intent intent) { + final String action = intent.getAction(); + if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(action)) { + mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR); + } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) { + mHandler.sendEmptyMessage(H.UPDATE_RINGER_MODE); + } + } + } + + // === Indexing === + + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = + new BaseSearchIndexProvider() { + + public List getXmlResourcesToIndex( + Context context, boolean enabled) { + final SearchIndexableResource sir = new SearchIndexableResource(context); + sir.xmlResId = R.xml.sounds; + return Arrays.asList(sir); + } + + public List getNonIndexableKeys(Context context) { + final ArrayList rt = new ArrayList(); + if (Utils.isVoiceCapable(context)) { + rt.add(KEY_NOTIFICATION_VOLUME); + } else { + rt.add(KEY_RING_VOLUME); + rt.add(KEY_PHONE_RINGTONE); + rt.add(KEY_WIFI_DISPLAY); + rt.add(KEY_VIBRATE_WHEN_RINGING); + } + return rt; + } + }; +} diff --git a/src/com/android/settings/notification/VolumeSeekBarPreference.java b/src/com/android/settings/notification/VolumeSeekBarPreference.java index cb2fa90..49bd815 100644 --- a/src/com/android/settings/notification/VolumeSeekBarPreference.java +++ b/src/com/android/settings/notification/VolumeSeekBarPreference.java @@ -138,7 +138,9 @@ public class VolumeSeekBarPreference extends SeekBarPreference mVolumizer.start(); mVolumizer.setSeekBar(mSeekBar); updateIconView(); - mCallback.onStreamValueChanged(mStream, mSeekBar.getProgress()); + if (mCallback != null) { + mCallback.onStreamValueChanged(mStream, mSeekBar.getProgress()); + } updateSuppressionText(); if (!isEnabled()) { mSeekBar.setEnabled(false); @@ -150,7 +152,9 @@ public class VolumeSeekBarPreference extends SeekBarPreference @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) { super.onProgressChanged(seekBar, progress, fromTouch); - mCallback.onStreamValueChanged(mStream, progress); + if (mCallback != null) { + mCallback.onStreamValueChanged(mStream, progress); + } } private void updateIconView() { diff --git a/src/com/android/settings/search/IndexDatabaseHelper.java b/src/com/android/settings/search/IndexDatabaseHelper.java index 152cbf3..273960d 100644 --- a/src/com/android/settings/search/IndexDatabaseHelper.java +++ b/src/com/android/settings/search/IndexDatabaseHelper.java @@ -28,7 +28,7 @@ public class IndexDatabaseHelper extends SQLiteOpenHelper { private static final String TAG = "IndexDatabaseHelper"; private static final String DATABASE_NAME = "search_index.db"; - private static final int DATABASE_VERSION = 115; + private static final int DATABASE_VERSION = 116; public interface Tables { public static final String TABLE_PREFS_INDEX = "prefs_index"; diff --git a/src/com/android/settings/search/Ranking.java b/src/com/android/settings/search/Ranking.java index 591fb67..2dc1a89 100644 --- a/src/com/android/settings/search/Ranking.java +++ b/src/com/android/settings/search/Ranking.java @@ -40,8 +40,9 @@ import com.android.settings.inputmethod.InputMethodAndLanguageSettings; import com.android.settings.location.LocationSettings; import com.android.settings.location.ScanningSettings; import com.android.settings.net.DataUsageMeteredSettings; -import com.android.settings.notification.NotificationSettings; +import com.android.settings.notification.NotificationManagerSettings; import com.android.settings.notification.OtherSoundSettings; +import com.android.settings.notification.SoundSettings; import com.android.settings.notification.ZenModeAutomationSettings; import com.android.settings.notification.ZenModePrioritySettings; import com.android.settings.notification.ZenModeSettings; @@ -121,7 +122,8 @@ public final class Ranking { sRankMap.put(WallpaperTypeSettings.class.getName(), RANK_WALLPAPER); // Notifications - sRankMap.put(NotificationSettings.class.getName(), RANK_NOTIFICATIONS); + sRankMap.put(SoundSettings.class.getName(), RANK_NOTIFICATIONS); + sRankMap.put(NotificationManagerSettings.class.getName(), RANK_NOTIFICATIONS); sRankMap.put(OtherSoundSettings.class.getName(), RANK_NOTIFICATIONS); sRankMap.put(ZenModeSettings.class.getName(), RANK_NOTIFICATIONS); sRankMap.put(ZenModePrioritySettings.class.getName(), RANK_NOTIFICATIONS); diff --git a/src/com/android/settings/search/SearchIndexableResources.java b/src/com/android/settings/search/SearchIndexableResources.java index 2f67383..a7a8264 100644 --- a/src/com/android/settings/search/SearchIndexableResources.java +++ b/src/com/android/settings/search/SearchIndexableResources.java @@ -42,8 +42,9 @@ import com.android.settings.inputmethod.InputMethodAndLanguageSettings; import com.android.settings.location.LocationSettings; import com.android.settings.location.ScanningSettings; import com.android.settings.net.DataUsageMeteredSettings; -import com.android.settings.notification.NotificationSettings; +import com.android.settings.notification.NotificationManagerSettings; import com.android.settings.notification.OtherSoundSettings; +import com.android.settings.notification.SoundSettings; import com.android.settings.notification.ZenModePrioritySettings; import com.android.settings.notification.ZenModeSettings; import com.android.settings.print.PrintSettingsFragment; @@ -120,6 +121,13 @@ public final class SearchIndexableResources { WirelessSettings.class.getName(), R.drawable.ic_settings_more)); + sResMap.put(SecuritySettings.class.getName(), + new SearchIndexableResource( + Ranking.getRankForClassName(SecuritySettings.class.getName()), + NO_DATA_RES_ID, + SecuritySettings.class.getName(), + R.drawable.ic_settings_security)); + sResMap.put(HomeSettings.class.getName(), new SearchIndexableResource( Ranking.getRankForClassName(HomeSettings.class.getName()), @@ -141,11 +149,18 @@ public final class SearchIndexableResources { WallpaperTypeSettings.class.getName(), R.drawable.ic_settings_display)); - sResMap.put(NotificationSettings.class.getName(), + sResMap.put(SoundSettings.class.getName(), + new SearchIndexableResource( + Ranking.getRankForClassName(SoundSettings.class.getName()), + NO_DATA_RES_ID, + SoundSettings.class.getName(), + R.drawable.ic_settings_notifications)); + + sResMap.put(NotificationManagerSettings.class.getName(), new SearchIndexableResource( - Ranking.getRankForClassName(NotificationSettings.class.getName()), + Ranking.getRankForClassName(NotificationManagerSettings.class.getName()), NO_DATA_RES_ID, - NotificationSettings.class.getName(), + NotificationManagerSettings.class.getName(), R.drawable.ic_settings_notifications)); sResMap.put(OtherSoundSettings.class.getName(), -- cgit v1.1