summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDanny Baumann <dannybaumann@web.de>2013-11-07 10:43:02 +0100
committerAdnan Begovic <adnan@cyngn.com>2015-10-29 17:36:29 -0700
commita284b34f11b3ad22084232950d81fb1bc68f21ce (patch)
tree24a6b7f480465209bb128d3d3fa4e36fd85c3250
parentaf88d809c0354ef2551050b2ea74cb85dc8ef056 (diff)
downloadpackages_apps_Settings-a284b34f11b3ad22084232950d81fb1bc68f21ce.zip
packages_apps_Settings-a284b34f11b3ad22084232950d81fb1bc68f21ce.tar.gz
packages_apps_Settings-a284b34f11b3ad22084232950d81fb1bc68f21ce.tar.bz2
settings: Squashed commit of CMHW features
Add hardware tunables (gamma, color, vibration strength). Change-Id: I44e3e4e6cb444498a7c56048618cd92a0e2b8e59 Settings: restore hardware tunable values on boot Change-Id: I9d2720947d615cab6a7ab9b596b24b8033dd0b4f Settings: Add default value for display color control (2/2) Change-Id: I50b684abe504c21ef49492f99b18873d75509697 settings: Move headset option, hide MoreDeviceSettings if empty * This option fits much better in the sound menu under "automation and effects", and on many devices it's the only option in the "More..." menu under Tap & Pay. * Move it, and remove the MoreDeviceSettings top-level category if there's nothing else in it. Change-Id: Idd82f582a1ba54f8b45fbd4fbe631057e9515f86 Remove 'More device settings' menu Change-Id: I86cd84f6f6c408b26c04d92529e9a031c4fed1f7 DisplayColor: Properly handle a minValue * Previously setting anything as a minValue would cause the percentages to get out of whack. For instance, setting it to 35 would cause the maximum percentage to climb above 100% as well as still allowing the value to be set lower than the min. * This makes the maximum for the slider the max value minus the min (so we get the proper spread for min to max) and then adds the min back on before setting so we can't possibly go below the min. Change-Id: I8dcdc422f54847940351fae10c74af6301d1e1be Settings: AdaptiveBacklight support Add support for adaptive backlight technologies like NVIDIA SmartDimmer, QCOM CABL or Samsung CABC. Patchset 2: Use internal shared prefs to store the smardimmer setting Patchset 3: Rename to AdaptiveBacklight Patchset 4: Reorganize settings and strings to follow design guidelines Patchset 5: CleanUp Patchset 6: Added suggestions Patchset 7: Sync default value. CleanUp. Depends on http://review.cyanogenmod.org/#/c/48465/ Change-Id: I52cb990f36593b265a00b46a5f63590515822ea5 settings: Add support for SRE * Add support for sunlight readability enhancement * Optionally depends on adaptive backlight, depending on HAL Change-Id: I9ca388ffd68080f0e497edb81d5f8616c194ea1d Cleanup. Now that button and keyboard backlight don't use the HW framework anymore, there's no point in having an abstraction for a single use case. Change-Id: Ib66b2a29a105d53e3ba4273abb06977b132c1fc8
-rw-r--r--proguard.flags1
-rw-r--r--res/drawable/color_tuning_preview.xml24
-rw-r--r--res/layout/display_color_calibration.xml89
-rw-r--r--res/layout/display_gamma_calibration.xml32
-rw-r--r--res/layout/display_gamma_calibration_header.xml26
-rw-r--r--res/layout/display_gamma_calibration_item.xml37
-rw-r--r--res/layout/vibrator_intensity.xml58
-rw-r--r--res/values/cm_arrays.xml5
-rw-r--r--res/values/cm_strings.xml38
-rw-r--r--res/xml/display_settings.xml34
-rw-r--r--res/xml/other_sound_settings.xml7
-rw-r--r--src/com/android/settings/ButtonSettings.java3
-rw-r--r--src/com/android/settings/DisplaySettings.java137
-rw-r--r--src/com/android/settings/cyanogenmod/BootReceiver.java7
-rw-r--r--src/com/android/settings/hardware/DisplayColor.java268
-rw-r--r--src/com/android/settings/hardware/DisplayGamma.java341
-rw-r--r--src/com/android/settings/hardware/VibratorIntensity.java216
-rw-r--r--src/com/android/settings/notification/OtherSoundSettings.java12
18 files changed, 1331 insertions, 4 deletions
diff --git a/proguard.flags b/proguard.flags
index 578ff4d..8ce16c8 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -16,6 +16,7 @@
-keep class com.android.settings.users.*
-keep class com.android.settings.nfc.*
-keep class com.android.settings.notification.*
+-keep class com.android.settings.cyanogenmod.*Settings
# Keep click responders
-keepclassmembers class com.android.settings.inputmethod.UserDictionaryAddWordActivity {
diff --git a/res/drawable/color_tuning_preview.xml b/res/drawable/color_tuning_preview.xml
new file mode 100644
index 0000000..589237a
--- /dev/null
+++ b/res/drawable/color_tuning_preview.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+
+ <gradient
+ android:angle="0"
+ android:startColor="#000000"
+ android:endColor="#FFFFFF" />
+</shape>
diff --git a/res/layout/display_color_calibration.xml b/res/layout/display_color_calibration.xml
new file mode 100644
index 0000000..72d6ded
--- /dev/null
+++ b/res/layout/display_color_calibration.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:paddingStart="20dip"
+ android:paddingEnd="20dip"
+ android:paddingBottom="20dip">
+
+ <TextView android:id="@+id/color_red_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/color_red_title"
+ android:paddingTop="10dip" />
+ <TextView android:id="@+id/color_red_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip" />
+ <SeekBar android:id="@+id/color_red_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_red_text"
+ android:paddingTop="2dip" />
+
+ <TextView android:id="@+id/color_green_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_red_seekbar"
+ android:text="@string/color_green_title"
+ android:paddingTop="10dip" />
+ <TextView android:id="@+id/color_green_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_red_seekbar"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip" />
+ <SeekBar android:id="@+id/color_green_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_green_text"
+ android:paddingTop="2dip" />
+
+ <TextView android:id="@+id/color_blue_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_green_seekbar"
+ android:text="@string/color_blue_title"
+ android:paddingTop="10dip" />
+ <TextView android:id="@+id/color_blue_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_green_seekbar"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip" />
+ <SeekBar android:id="@+id/color_blue_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_blue_text"
+ android:paddingTop="2dip" />
+
+ <ImageView android:id="@+id/black_scale_picture_color"
+ android:src="@drawable/color_tuning_preview"
+ android:layout_width="match_parent"
+ android:layout_height="40dip"
+ android:layout_below="@id/color_blue_seekbar"
+ android:paddingTop="20dip" />
+
+ </RelativeLayout>
+</ScrollView>
diff --git a/res/layout/display_gamma_calibration.xml b/res/layout/display_gamma_calibration.xml
new file mode 100644
index 0000000..db66f7f
--- /dev/null
+++ b/res/layout/display_gamma_calibration.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <LinearLayout
+ android:id="@+id/gamma_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:orientation="vertical"
+ android:paddingBottom="20dp" >
+
+ <!-- children will be filled in dynamically -->
+
+ </LinearLayout>
+</ScrollView>
diff --git a/res/layout/display_gamma_calibration_header.xml b/res/layout/display_gamma_calibration_header.xml
new file mode 100644
index 0000000..8e2b86d
--- /dev/null
+++ b/res/layout/display_gamma_calibration_header.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="5dp"
+ android:layout_marginEnd="5dp"
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:paddingTop="10dp"
+ android:paddingBottom="5dp" >
+
+</TextView>
diff --git a/res/layout/display_gamma_calibration_item.xml b/res/layout/display_gamma_calibration_item.xml
new file mode 100644
index 0000000..bd560a7
--- /dev/null
+++ b/res/layout/display_gamma_calibration_item.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="20dip"
+ android:paddingEnd="20dip"
+ android:paddingTop="10dip" >
+
+ <TextView android:id="@+id/color_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <TextView android:id="@+id/color_value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true" />
+ <SeekBar android:id="@+id/color_seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/color_text"
+ android:paddingTop="2dip" />
+
+</RelativeLayout>
diff --git a/res/layout/vibrator_intensity.xml b/res/layout/vibrator_intensity.xml
new file mode 100644
index 0000000..dcbc676
--- /dev/null
+++ b/res/layout/vibrator_intensity.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
+
+ <RelativeLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center_horizontal"
+ android:paddingBottom="20dip">
+
+ <TextView android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/vibrator_intensity_title"
+ android:paddingTop="10dip"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip" />
+ <TextView android:id="@+id/value"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentRight="true"
+ android:paddingTop="10dip"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip" />
+ <SeekBar android:id="@*android:id/seekbar"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@id/text"
+ android:paddingTop="2dip"
+ android:paddingLeft="20dip"
+ android:paddingRight="20dip" />
+
+ <TextView
+ android:id="@+id/warning_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_below="@*android:id/seekbar"
+ android:paddingTop="8dip"
+ android:gravity="center"
+ android:textSize="15dp" />
+
+ </RelativeLayout>
+</ScrollView>
diff --git a/res/values/cm_arrays.xml b/res/values/cm_arrays.xml
index 2c4e19b..2e4dac8 100644
--- a/res/values/cm_arrays.xml
+++ b/res/values/cm_arrays.xml
@@ -256,4 +256,9 @@
<item>users</item>
<item>bugreport</item>
</string-array>
+
+ <!-- Gamma calibration descriptors, deliberately empty as string values populated via
+ per-device overlay. Required to build on non-hardware tunable devices -->
+ <string-array name="gamma_descriptors" translatable="false">
+ </string-array>
</resources>
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 329f657..d827e94 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -361,6 +361,18 @@
<string name="home_answer_call_title">Answer call</string>
<string name="home_answer_call_summary">Pressing the home button will answer the current incoming call</string>
+ <!-- Backlight brightness settings screen -->
+ <string name="adaptive_backlight_title">Adaptive backlight</string>
+ <string name="adaptive_backlight_summary">Dynamically adjust the brightness of the display\'s backlight to maximize battery life while maintaining usability</string>
+
+ <!-- Sunlight readability enhancement screen -->
+ <string name="sunlight_enhancement_title">Sunlight enhancement</string>
+ <string name="sunlight_enhancement_summary">Enhance display brightness and readability under bright sunlight</string>
+
+ <!-- Color enhancement settings screen -->
+ <string name="color_enhancement_title">Color enhancement</string>
+ <string name="color_enhancement_summary">Dynamically enhance the color of the display</string>
+
<!-- Key backlight -->
<string name="button_backlight_title">Backlight</string>
<string name="button_backlight_enabled">Illuminate buttons</string>
@@ -421,4 +433,30 @@
<!-- Font size sample text. This needs to be a very short string, as it is shown in
multiple font sizes in a limited amount of space. -->
<string name="font_size_sample">Sample</string>
+
+ <!-- Hardware tunables - Vibrator intensity -->
+ <string name="vibrator_intensity_title">Vibrator intensity</string>
+ <string name="vibrator_warning">Values higher than %1$d are not recommended</string>
+
+ <!-- Hardware tunables - Color calibration -->
+ <string name="color_calibration_title">Color calibration</string>
+ <string name="color_calibration_summary">Calibrate on-screen colors</string>
+ <string name="color_red_title">Red</string>
+ <string name="color_green_title">Green</string>
+ <string name="color_blue_title">Blue</string>
+
+ <!-- Hardware tunables - Gamma calibration -->
+ <string name="gamma_tuning_title_head">Gamma calibration</string>
+ <string name="gamma_tuning_summary_head">Tweak gamma values</string>
+ <string name="gamma_tuning_control_set_header">Group <xliff:g id="index">%d</xliff:g></string> <!-- used if no name provided by overlay -->
+ <string name="gamma_tuning_contrast">Contrast</string>
+ <string name="gamma_tuning_brightness">Brightness</string>
+ <string name="gamma_tuning_saturation">Saturation</string>
+
+ <!-- Launch music player when headset is connected -->
+ <string name="headset_connect_player_title">Launch music app</string>
+ <string name="headset_connect_player_summary">Launch the default music app when headset is connected</string>
+
+ <string name="auto_brightness_reset_button">Reset</string>
+
</resources>
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 1963055..48f76bc 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -95,6 +95,7 @@
android:title="@string/wifi_display_settings_title"
settings:keywords="@string/keywords_display_cast_screen"
android:fragment="com.android.settings.wfd.WifiDisplaySettings" />
+
<PreferenceCategory
android:key="advanced_display_prefs"
android:title="@string/advanced_settings">
@@ -120,5 +121,38 @@
android:title="@string/wake_when_plugged_or_unplugged_title"
android:summary="@string/wake_when_plugged_or_unplugged_summary"
android:defaultValue="false" />
+
+ <SwitchPreference
+ android:key="adaptive_backlight"
+ android:title="@string/adaptive_backlight_title"
+ android:summary="@string/adaptive_backlight_summary"
+ android:defaultValue="true" />
+
+ <SwitchPreference
+ android:key="sunlight_enhancement"
+ android:title="@string/sunlight_enhancement_title"
+ android:summary="@string/sunlight_enhancement_summary"
+ android:defaultValue="true" />
+
+ <SwitchPreference
+ android:key="color_enhancement"
+ android:title="@string/color_enhancement_title"
+ android:summary="@string/color_enhancement_summary"
+ android:defaultValue="true" />
+
+
+ <com.android.settings.hardware.DisplayColor
+ android:key="color_calibration"
+ android:title="@string/color_calibration_title"
+ android:dialogTitle="@string/color_calibration_title"
+ android:summary="@string/color_calibration_summary"
+ android:persistent="false" />
+
+ <com.android.settings.hardware.DisplayGamma
+ android:key="gamma_tuning"
+ android:title="@string/gamma_tuning_title_head"
+ android:dialogTitle="@string/gamma_tuning_title_head"
+ android:summary="@string/gamma_tuning_summary_head"
+ android:persistent="false" />
</PreferenceCategory>
</PreferenceScreen>
diff --git a/res/xml/other_sound_settings.xml b/res/xml/other_sound_settings.xml
index cc88c3f..328c0a5 100644
--- a/res/xml/other_sound_settings.xml
+++ b/res/xml/other_sound_settings.xml
@@ -55,6 +55,13 @@
android:title="@string/vibrate_on_touch_title"
android:persistent="false" />
+ <!-- CMHW vibration intensity -->
+ <com.android.settings.hardware.VibratorIntensity
+ android:key="vibration_intensity"
+ android:title="@string/vibrator_intensity_title"
+ android:dialogTitle="@string/vibrator_intensity_title"
+ android:persistent="false" />
+
<!-- Dock speaker plays -->
<com.android.settings.DropDownPreference
android:key="dock_audio_media"
diff --git a/src/com/android/settings/ButtonSettings.java b/src/com/android/settings/ButtonSettings.java
index b0a52e8..85d1541 100644
--- a/src/com/android/settings/ButtonSettings.java
+++ b/src/com/android/settings/ButtonSettings.java
@@ -70,11 +70,8 @@ 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";
-<<<<<<< HEAD
private static final String KEY_BLUETOOTH_INPUT_SETTINGS = "bluetooth_input_settings";
-=======
private static final String KEY_VOLUME_MUSIC_CONTROLS = "volbtn_music_controls";
->>>>>>> e9fe965... Settings: set volume wake dependency in code
private static final String CATEGORY_POWER = "power_key";
private static final String CATEGORY_HOME = "home_key";
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 66af458..13c1b28 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2014 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.
@@ -48,6 +49,7 @@ import android.os.RemoteException;
import android.os.SystemProperties;
import android.preference.ListPreference;
import android.preference.Preference;
+import android.preference.PreferenceManager;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
@@ -58,10 +60,17 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
+
import java.util.ArrayList;
import java.util.List;
import com.android.settings.Utils;
+import com.android.settings.hardware.DisplayColor;
+import com.android.settings.hardware.DisplayGamma;
+
+import org.cyanogenmod.hardware.AdaptiveBacklight;
+import org.cyanogenmod.hardware.ColorEnhancement;
+import org.cyanogenmod.hardware.SunlightEnhancement;
import org.cyanogenmod.hardware.TapToWake;
public class DisplaySettings extends SettingsPreferenceFragment implements
@@ -80,11 +89,16 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
private static final String KEY_AUTO_BRIGHTNESS = "auto_brightness";
private static final String KEY_AUTO_ROTATE = "auto_rotate";
private static final String KEY_NIGHT_MODE = "night_mode";
+ private static final String KEY_ADAPTIVE_BACKLIGHT = "adaptive_backlight";
+ private static final String KEY_SUNLIGHT_ENHANCEMENT = "sunlight_enhancement";
+ private static final String KEY_COLOR_ENHANCEMENT = "color_enhancement";
private static final String KEY_TAP_TO_WAKE = "double_tap_wake_gesture";
private static final String KEY_PROXIMITY_WAKE = "proximity_on_wake";
private static final String KEY_WAKE_WHEN_PLUGGED_OR_UNPLUGGED = "wake_when_plugged_or_unplugged";
private static final String CATEGORY_ADVANCED = "advanced_display_prefs";
+ private static final String KEY_DISPLAY_COLOR = "color_calibration";
+ private static final String KEY_DISPLAY_GAMMA = "gamma_tuning";
private static final int DLG_GLOBAL_CHANGE_WARNING = 1;
@@ -102,6 +116,10 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
private SwitchPreference mTapToWake;
private SwitchPreference mWakeWhenPluggedOrUnplugged;
+ private SwitchPreference mAdaptiveBacklight;
+ private SwitchPreference mSunlightEnhancement;
+ private SwitchPreference mColorEnhancement;
+
@Override
protected int getMetricsCategory() {
return MetricsLogger.DISPLAY;
@@ -148,6 +166,33 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
removePreference(KEY_LIFT_TO_WAKE);
}
+ PreferenceCategory advancedPrefs = (PreferenceCategory) findPreference(CATEGORY_ADVANCED);
+
+ mAdaptiveBacklight = (SwitchPreference) findPreference(KEY_ADAPTIVE_BACKLIGHT);
+ if (!isAdaptiveBacklightSupported()) {
+ advancedPrefs.removePreference(mAdaptiveBacklight);
+ mAdaptiveBacklight = null;
+ }
+
+ mSunlightEnhancement = (SwitchPreference) findPreference(KEY_SUNLIGHT_ENHANCEMENT);
+ if (!isSunlightEnhancementSupported()) {
+ advancedPrefs.removePreference(mSunlightEnhancement);
+ mSunlightEnhancement = null;
+ }
+
+ mColorEnhancement = (SwitchPreference) findPreference(KEY_COLOR_ENHANCEMENT);
+ if (!isColorEnhancementSupported()) {
+ advancedPrefs.removePreference(mColorEnhancement);
+ mColorEnhancement = null;
+ }
+
+ if (!DisplayColor.isSupported()) {
+ advancedPrefs.removePreference(findPreference(KEY_DISPLAY_COLOR));
+ }
+ if (!DisplayGamma.isSupported()) {
+ advancedPrefs.removePreference(findPreference(KEY_DISPLAY_GAMMA));
+ }
+
mDozePreference = (SwitchPreference) findPreference(KEY_DOZE);
if (mDozePreference != null && Utils.isDozeAvailable(activity)) {
mDozePreference.setOnPreferenceChangeListener(this);
@@ -208,7 +253,6 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
mNightModePreference.setValue(String.valueOf(currentNightMode));
mNightModePreference.setOnPreferenceChangeListener(this);
}
- PreferenceCategory advancedPrefs = (PreferenceCategory) findPreference(CATEGORY_ADVANCED);
mTapToWake = (SwitchPreference) findPreference(KEY_TAP_TO_WAKE);
if (!isTapToWakeSupported()) {
@@ -316,6 +360,23 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
public void onResume() {
super.onResume();
+ if (mAdaptiveBacklight != null) {
+ mAdaptiveBacklight.setChecked(AdaptiveBacklight.isEnabled());
+ }
+
+ if (mSunlightEnhancement != null) {
+ if (SunlightEnhancement.isAdaptiveBacklightRequired() &&
+ !AdaptiveBacklight.isEnabled()) {
+ mSunlightEnhancement.setEnabled(false);
+ } else {
+ mSunlightEnhancement.setChecked(SunlightEnhancement.isEnabled());
+ }
+ }
+
+ if (mColorEnhancement != null) {
+ mColorEnhancement.setChecked(ColorEnhancement.isEnabled());
+ }
+
if (mTapToWake != null) {
mTapToWake.setChecked(TapToWake.isEnabled());
}
@@ -420,6 +481,16 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
if (preference == mTapToWake) {
return TapToWake.setEnabled(mTapToWake.isChecked());
+ } else if (preference == mAdaptiveBacklight) {
+ if (mSunlightEnhancement != null &&
+ SunlightEnhancement.isAdaptiveBacklightRequired()) {
+ mSunlightEnhancement.setEnabled(mAdaptiveBacklight.isChecked());
+ }
+ return AdaptiveBacklight.setEnabled(mAdaptiveBacklight.isChecked());
+ } else if (preference == mSunlightEnhancement) {
+ return SunlightEnhancement.setEnabled(mSunlightEnhancement.isChecked());
+ } else if (preference == mColorEnhancement) {
+ return ColorEnhancement.setEnabled(mColorEnhancement.isChecked());
} else if (preference == mWakeWhenPluggedOrUnplugged) {
Settings.Global.putInt(getContentResolver(),
Settings.Global.WAKE_WHEN_PLUGGED_OR_UNPLUGGED,
@@ -502,12 +573,76 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
if (isTapToWakeSupported()) {
final boolean enabled = prefs.getBoolean(KEY_TAP_TO_WAKE,
TapToWake.isEnabled());
+
if (!TapToWake.setEnabled(enabled)) {
Log.e(TAG, "Failed to restore tap-to-wake settings.");
} else {
Log.d(TAG, "Tap-to-wake settings restored.");
}
}
+
+ if (isAdaptiveBacklightSupported()) {
+ final boolean enabled = prefs.getBoolean(KEY_ADAPTIVE_BACKLIGHT,
+ AdaptiveBacklight.isEnabled());
+ if (!AdaptiveBacklight.setEnabled(enabled)) {
+ Log.e(TAG, "Failed to restore adaptive backlight settings.");
+ } else {
+ Log.d(TAG, "Adaptive backlight settings restored.");
+ }
+ }
+
+ if (isSunlightEnhancementSupported()) {
+ final boolean enabled = prefs.getBoolean(KEY_SUNLIGHT_ENHANCEMENT,
+ SunlightEnhancement.isEnabled());
+ if (SunlightEnhancement.isAdaptiveBacklightRequired() &&
+ !AdaptiveBacklight.isEnabled()) {
+ SunlightEnhancement.setEnabled(false);
+ Log.d(TAG, "SRE requires CABC, disabled");
+ } else {
+ if (!SunlightEnhancement.setEnabled(enabled)) {
+ Log.e(TAG, "Failed to restore SRE settings.");
+ } else {
+ Log.d(TAG, "SRE settings restored.");
+ }
+ }
+ }
+
+ if (isColorEnhancementSupported()) {
+ final boolean enabled = prefs.getBoolean(KEY_COLOR_ENHANCEMENT,
+ ColorEnhancement.isEnabled());
+ if (!ColorEnhancement.setEnabled(enabled)) {
+ Log.e(TAG, "Failed to restore color enhancement settings.");
+ } else {
+ Log.d(TAG, "Color enhancement settings restored.");
+ }
+ }
+ }
+
+ private static boolean isAdaptiveBacklightSupported() {
+ try {
+ return AdaptiveBacklight.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework not installed
+ return false;
+ }
+ }
+
+ private static boolean isSunlightEnhancementSupported() {
+ try {
+ return SunlightEnhancement.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework not installed
+ return false;
+ }
+ }
+
+ private static boolean isColorEnhancementSupported() {
+ try {
+ return ColorEnhancement.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework not installed
+ return false;
+ }
}
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
diff --git a/src/com/android/settings/cyanogenmod/BootReceiver.java b/src/com/android/settings/cyanogenmod/BootReceiver.java
index 18213d7..9d32b02 100644
--- a/src/com/android/settings/cyanogenmod/BootReceiver.java
+++ b/src/com/android/settings/cyanogenmod/BootReceiver.java
@@ -21,6 +21,9 @@ import android.content.Context;
import android.content.Intent;
import com.android.settings.ButtonSettings;
import com.android.settings.DisplaySettings;
+import com.android.settings.hardware.DisplayColor;
+import com.android.settings.hardware.DisplayGamma;
+import com.android.settings.hardware.VibratorIntensity;
public class BootReceiver extends BroadcastReceiver {
@@ -31,5 +34,9 @@ public class BootReceiver extends BroadcastReceiver {
/* Restore the hardware tunable values */
DisplaySettings.restore(ctx);
ButtonSettings.restoreKeyDisabler(ctx);
+ DisplayColor.restore(ctx);
+ DisplayGamma.restore(ctx);
+ VibratorIntensity.restore(ctx);
+ DisplaySettings.restore(ctx);
}
}
diff --git a/src/com/android/settings/hardware/DisplayColor.java b/src/com/android/settings/hardware/DisplayColor.java
new file mode 100644
index 0000000..f9dd845
--- /dev/null
+++ b/src/com/android/settings/hardware/DisplayColor.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2013 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.hardware;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.Button;
+
+import com.android.settings.R;
+
+import org.cyanogenmod.hardware.DisplayColorCalibration;
+
+/**
+ * Special preference type that allows configuration of Color settings
+ */
+public class DisplayColor extends DialogPreference {
+ private static final String TAG = "ColorCalibration";
+
+ // These arrays must all match in length and order
+ private static final int[] SEEKBAR_ID = new int[] {
+ R.id.color_red_seekbar,
+ R.id.color_green_seekbar,
+ R.id.color_blue_seekbar
+ };
+
+ private static final int[] SEEKBAR_VALUE_ID = new int[] {
+ R.id.color_red_value,
+ R.id.color_green_value,
+ R.id.color_blue_value
+ };
+
+ private ColorSeekBar[] mSeekBars = new ColorSeekBar[SEEKBAR_ID.length];
+ private String[] mCurrentColors;
+ private String mOriginalColors;
+
+ public DisplayColor(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ if (!isSupported()) {
+ return;
+ }
+
+ setDialogLayoutResource(R.layout.display_color_calibration);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ builder.setNeutralButton(R.string.auto_brightness_reset_button,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mOriginalColors = DisplayColorCalibration.getCurColors();
+ mCurrentColors = mOriginalColors.split(" ");
+
+ for (int i = 0; i < SEEKBAR_ID.length; i++) {
+ SeekBar seekBar = (SeekBar) view.findViewById(SEEKBAR_ID[i]);
+ TextView value = (TextView) view.findViewById(SEEKBAR_VALUE_ID[i]);
+ mSeekBars[i] = new ColorSeekBar(seekBar, value, i);
+ mSeekBars[i].setValueFromString(mCurrentColors[i]);
+ }
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ super.showDialog(state);
+
+ // Can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ AlertDialog d = (AlertDialog) getDialog();
+ Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL);
+ defaultsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ int defaultValue = DisplayColorCalibration.getDefValue();
+ for (int i = 0; i < mSeekBars.length; i++) {
+ mSeekBars[i].mSeekBar.setProgress(defaultValue);
+ mCurrentColors[i] = String.valueOf(defaultValue);
+ }
+ DisplayColorCalibration.setColors(TextUtils.join(" ", mCurrentColors));
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ if (positiveResult) {
+ Editor editor = getEditor();
+ editor.putString("display_color_calibration", DisplayColorCalibration.getCurColors());
+ editor.commit();
+ } else if (mOriginalColors != null) {
+ DisplayColorCalibration.setColors(mOriginalColors);
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (getDialog() == null || !getDialog().isShowing()) {
+ return superState;
+ }
+
+ // Save the dialog state
+ final SavedState myState = new SavedState(superState);
+ myState.currentColors = mCurrentColors;
+ myState.originalColors = mOriginalColors;
+
+ // Restore the old state when the activity or dialog is being paused
+ DisplayColorCalibration.setColors(mOriginalColors);
+ mOriginalColors = null;
+
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ mOriginalColors = myState.originalColors;
+ mCurrentColors = myState.currentColors;
+ for (int i = 0; i < mSeekBars.length; i++) {
+ mSeekBars[i].setValueFromString(mCurrentColors[i]);
+ }
+ DisplayColorCalibration.setColors(TextUtils.join(" ", mCurrentColors));
+ }
+
+ public static boolean isSupported() {
+ try {
+ return DisplayColorCalibration.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework isn't installed
+ return false;
+ }
+ }
+
+ public static void restore(Context context) {
+ if (!isSupported()) {
+ return;
+ }
+
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ final String value = prefs.getString("display_color_calibration", null);
+
+ if (value != null) {
+ DisplayColorCalibration.setColors(value);
+ }
+ }
+
+ private static class SavedState extends BaseSavedState {
+ String originalColors;
+ String[] currentColors;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ originalColors = source.readString();
+ currentColors = source.createStringArray();
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeString(originalColors);
+ dest.writeStringArray(currentColors);
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ private class ColorSeekBar implements SeekBar.OnSeekBarChangeListener {
+ private int mIndex;
+ private SeekBar mSeekBar;
+ private TextView mValue;
+
+ public ColorSeekBar(SeekBar seekBar, TextView value, int index) {
+ mSeekBar = seekBar;
+ mValue = value;
+ mIndex = index;
+
+ mSeekBar.setMax(DisplayColorCalibration.getMaxValue() -
+ DisplayColorCalibration.getMinValue());
+ mSeekBar.setOnSeekBarChangeListener(this);
+ }
+
+ public void setValueFromString(String valueString) {
+ mSeekBar.setProgress(Integer.valueOf(valueString));
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ int min = DisplayColorCalibration.getMinValue();
+ int max = DisplayColorCalibration.getMaxValue();
+
+ if (fromUser) {
+ mCurrentColors[mIndex] = String.valueOf(progress + min);
+ DisplayColorCalibration.setColors(TextUtils.join(" ", mCurrentColors));
+ }
+
+ int percent = Math.round(100F * progress / (max - min));
+ mValue.setText(String.format("%d%%", percent));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+ }
+}
diff --git a/src/com/android/settings/hardware/DisplayGamma.java b/src/com/android/settings/hardware/DisplayGamma.java
new file mode 100644
index 0000000..5ce0390
--- /dev/null
+++ b/src/com/android/settings/hardware/DisplayGamma.java
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2013 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.hardware;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Resources;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.preference.DialogPreference;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import com.android.settings.R;
+import org.cyanogenmod.hardware.DisplayGammaCalibration;
+
+/**
+ * Special preference type that allows configuration of Gamma settings
+ */
+public class DisplayGamma extends DialogPreference {
+ private static final String TAG = "GammaCalibration";
+
+ private static final int[] BAR_COLORS = new int[] {
+ R.string.color_red_title,
+ R.string.color_green_title,
+ R.string.color_blue_title
+ };
+
+ private GammaSeekBar[][] mSeekBars;
+
+ private String[][] mCurrentColors;
+ private String[] mOriginalColors;
+ private int mNumberOfControls;
+
+ public DisplayGamma(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ if (!isSupported()) {
+ return;
+ }
+
+ mNumberOfControls = DisplayGammaCalibration.getNumberOfControls();
+ mSeekBars = new GammaSeekBar[mNumberOfControls][BAR_COLORS.length];
+
+ mOriginalColors = new String[mNumberOfControls];
+ mCurrentColors = new String[mNumberOfControls][];
+
+ setDialogLayoutResource(R.layout.display_gamma_calibration);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ builder.setNeutralButton(R.string.auto_brightness_reset_button,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ final ViewGroup container = (ViewGroup) view.findViewById(R.id.gamma_container);
+ final LayoutInflater inflater = LayoutInflater.from(getContext());
+ final SharedPreferences prefs = getSharedPreferences();
+ final Resources res = container.getResources();
+ final String[] gammaDescriptors = res.getStringArray(R.array.gamma_descriptors);
+
+ // Create multiple sets of seekbars, depending on the
+ // number of controls the device has
+ for (int index = 0; index < mNumberOfControls; index++) {
+ mOriginalColors[index] = DisplayGammaCalibration.getCurGamma(index);
+ mCurrentColors[index] = mOriginalColors[index].split(" ");
+
+ final String defaultKey = "display_gamma_default_" + index;
+ if (!prefs.contains(defaultKey)) {
+ prefs.edit().putString(defaultKey, mOriginalColors[index]).commit();
+ }
+
+ if (mNumberOfControls != 1) {
+ TextView header = (TextView) inflater.inflate(
+ R.layout.display_gamma_calibration_header, container, false);
+
+ if (index < gammaDescriptors.length) {
+ header.setText(gammaDescriptors[index]);
+ } else {
+ header.setText(res.getString(
+ R.string.gamma_tuning_control_set_header, index + 1));
+ }
+ container.addView(header);
+ }
+
+ for (int color = 0; color < BAR_COLORS.length; color++) {
+ ViewGroup item = (ViewGroup) inflater.inflate(
+ R.layout.display_gamma_calibration_item, container, false);
+
+ mSeekBars[index][color] = new GammaSeekBar(index, color, item);
+ mSeekBars[index][color].setGamma(Integer.valueOf(mCurrentColors[index][color]));
+ // make sure to add the seekbar group to the container _after_
+ // creating GammaSeekBar, so that GammaSeekBar has a chance to
+ // get the correct subviews without getting confused by duplicate IDs
+ container.addView(item);
+ }
+ }
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ super.showDialog(state);
+
+ // can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ AlertDialog d = (AlertDialog) getDialog();
+ Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL);
+ defaultsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ for (int index = 0; index < mSeekBars.length; index++) {
+ final SharedPreferences prefs = getSharedPreferences();
+ final String defaultKey = "display_gamma_default_" + index;
+ // this key is guaranteed to be present, as we have
+ // created it in onBindDialogView()
+ final String[] defaultColors = prefs.getString(defaultKey, null).split(" ");
+
+ for (int color = 0; color < BAR_COLORS.length; color++) {
+ mSeekBars[index][color].setGamma(Integer.valueOf(defaultColors[color]));
+ mCurrentColors[index][color] = defaultColors[color];
+ }
+ DisplayGammaCalibration.setGamma(index,
+ TextUtils.join(" ", mCurrentColors[index]));
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ if (positiveResult) {
+ Editor editor = getEditor();
+ for (int i = 0; i < mNumberOfControls; i++) {
+ editor.putString("display_gamma_" + i, DisplayGammaCalibration.getCurGamma(i));
+ }
+ editor.commit();
+ } else if (mOriginalColors != null) {
+ for (int i = 0; i < mNumberOfControls; i++) {
+ DisplayGammaCalibration.setGamma(i, mOriginalColors[i]);
+ }
+ }
+ }
+
+ @Override
+ protected Parcelable onSaveInstanceState() {
+ final Parcelable superState = super.onSaveInstanceState();
+ if (getDialog() == null || !getDialog().isShowing()) {
+ return superState;
+ }
+
+ // Save the dialog state
+ final SavedState myState = new SavedState(superState);
+ myState.controlCount = mNumberOfControls;
+ myState.currentColors = mCurrentColors;
+ myState.originalColors = mOriginalColors;
+
+ // Restore the old state when the activity or dialog is being paused
+ for (int i = 0; i < mNumberOfControls; i++) {
+ DisplayGammaCalibration.setGamma(i, mOriginalColors[i]);
+ }
+ mOriginalColors = null;
+
+ return myState;
+ }
+
+ @Override
+ protected void onRestoreInstanceState(Parcelable state) {
+ if (state == null || !state.getClass().equals(SavedState.class)) {
+ // Didn't save state for us in onSaveInstanceState
+ super.onRestoreInstanceState(state);
+ return;
+ }
+
+ SavedState myState = (SavedState) state;
+ super.onRestoreInstanceState(myState.getSuperState());
+ mNumberOfControls = myState.controlCount;
+ mOriginalColors = myState.originalColors;
+ mCurrentColors = myState.currentColors;
+
+ for (int index = 0; index < mNumberOfControls; index++) {
+ for (int color = 0; color < BAR_COLORS.length; color++) {
+ mSeekBars[index][color].setGamma(Integer.valueOf(mCurrentColors[index][color]));
+ }
+ DisplayGammaCalibration.setGamma(index, TextUtils.join(" ", mCurrentColors[index]));
+ }
+ }
+
+ public static boolean isSupported() {
+ try {
+ return DisplayGammaCalibration.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework isn't installed
+ return false;
+ }
+ }
+
+ public static void restore(Context context) {
+ if (!isSupported()) {
+ return;
+ }
+
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ for (int i = 0; i < DisplayGammaCalibration.getNumberOfControls(); i++) {
+ final String values = prefs.getString("display_gamma_" + i, null);
+ if (values != null) {
+ DisplayGammaCalibration.setGamma(i, values);
+ }
+ }
+ }
+
+ private static class SavedState extends BaseSavedState {
+ int controlCount;
+ String[] originalColors;
+ String[][] currentColors;
+
+ public SavedState(Parcelable superState) {
+ super(superState);
+ }
+
+ public SavedState(Parcel source) {
+ super(source);
+ controlCount = source.readInt();
+ originalColors = source.createStringArray();
+ currentColors = new String[controlCount][];
+ for (int i = 0; i < controlCount; i++) {
+ currentColors[i] = source.createStringArray();
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ dest.writeInt(controlCount);
+ dest.writeStringArray(originalColors);
+ for (int i = 0; i < controlCount; i++) {
+ dest.writeStringArray(currentColors[i]);
+ }
+ }
+
+ public static final Parcelable.Creator<SavedState> CREATOR =
+ new Parcelable.Creator<SavedState>() {
+
+ public SavedState createFromParcel(Parcel in) {
+ return new SavedState(in);
+ }
+
+ public SavedState[] newArray(int size) {
+ return new SavedState[size];
+ }
+ };
+ }
+
+ private class GammaSeekBar implements SeekBar.OnSeekBarChangeListener {
+ private int mControlIndex;
+ private int mColorIndex;
+ private int mOriginal;
+ private int mMin;
+ private SeekBar mSeekBar;
+ private TextView mValue;
+
+ public GammaSeekBar(int controlIndex, int colorIndex, ViewGroup container) {
+ mControlIndex = controlIndex;
+ mColorIndex = colorIndex;
+
+ mMin = DisplayGammaCalibration.getMinValue(controlIndex);
+
+ mValue = (TextView) container.findViewById(R.id.color_value);
+ mSeekBar = (SeekBar) container.findViewById(R.id.color_seekbar);
+
+ TextView label = (TextView) container.findViewById(R.id.color_text);
+ label.setText(container.getContext().getString(BAR_COLORS[colorIndex]));
+
+ mSeekBar.setMax(DisplayGammaCalibration.getMaxValue(controlIndex) - mMin);
+ mSeekBar.setProgress(0);
+ mValue.setText(String.valueOf(mSeekBar.getProgress() + mMin));
+
+ // this must be done last, we don't want to apply our initial value to the hardware
+ mSeekBar.setOnSeekBarChangeListener(this);
+ }
+
+ public void setGamma(int gamma) {
+ mSeekBar.setProgress(gamma - mMin);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if (fromUser) {
+ mCurrentColors[mControlIndex][mColorIndex] = String.valueOf(progress + mMin);
+ DisplayGammaCalibration.setGamma(mControlIndex,
+ TextUtils.join(" ", mCurrentColors[mControlIndex]));
+ }
+ mValue.setText(String.valueOf(progress + mMin));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ // Do nothing
+ }
+ }
+}
diff --git a/src/com/android/settings/hardware/VibratorIntensity.java b/src/com/android/settings/hardware/VibratorIntensity.java
new file mode 100644
index 0000000..346caa4
--- /dev/null
+++ b/src/com/android/settings/hardware/VibratorIntensity.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2013 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.hardware;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.graphics.Color;
+import android.graphics.LightingColorFilter;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.LayerDrawable;
+import android.os.Bundle;
+import android.os.Vibrator;
+import android.preference.DialogPreference;
+import android.preference.PreferenceManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.Button;
+
+import com.android.settings.R;
+import org.cyanogenmod.hardware.VibratorHW;
+
+public class VibratorIntensity extends DialogPreference implements
+ SeekBar.OnSeekBarChangeListener {
+ private static final String PREF_NAME = "vibrator_intensity";
+ private SeekBar mSeekBar;
+ private TextView mValue;
+ private TextView mWarning;
+ private int mOriginalValue;
+
+ private Drawable mProgressDrawable;
+ private Drawable mProgressThumb;
+ private LightingColorFilter mRedFilter;
+
+ public VibratorIntensity(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ if (!isSupported()) {
+ return;
+ }
+
+ setDialogLayoutResource(R.layout.vibrator_intensity);
+ }
+
+ @Override
+ protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
+ builder.setNeutralButton(R.string.auto_brightness_reset_button,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ }
+ });
+ }
+
+ @Override
+ protected void onBindDialogView(View view) {
+ super.onBindDialogView(view);
+
+ mSeekBar = (SeekBar) view.findViewById(com.android.internal.R.id.seekbar);
+ mValue = (TextView) view.findViewById(R.id.value);
+ mWarning = (TextView) view.findViewById(R.id.warning_text);
+
+ int warningThreshold = VibratorHW.getWarningThreshold();
+ if (warningThreshold > 0) {
+ String message = getContext().getResources().getString(
+ R.string.vibrator_warning, intensityToPercent(warningThreshold));
+ mWarning.setText(message);
+ } else if (mWarning != null) {
+ mWarning.setVisibility(View.GONE);
+ }
+
+ Drawable progressDrawable = mSeekBar.getProgressDrawable();
+ if (progressDrawable instanceof LayerDrawable) {
+ LayerDrawable ld = (LayerDrawable) progressDrawable;
+ mProgressDrawable = ld.findDrawableByLayerId(android.R.id.progress);
+ }
+ mProgressThumb = mSeekBar.getThumb();
+ mRedFilter = new LightingColorFilter(Color.BLACK,
+ getContext().getResources().getColor(android.R.color.holo_red_light));
+
+ // Read the current value in case user wants to dismiss his changes
+ mOriginalValue = VibratorHW.getCurIntensity();
+
+ // Restore percent value from SharedPreferences object
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+ int defaultValue = intensityToPercent(VibratorHW.getDefaultIntensity());
+ int percent = prefs.getInt(PREF_NAME, defaultValue);
+
+ mSeekBar.setOnSeekBarChangeListener(this);
+ mSeekBar.setProgress(percent);
+ }
+
+ @Override
+ protected void showDialog(Bundle state) {
+ super.showDialog(state);
+
+ // Can't use onPrepareDialogBuilder for this as we want the dialog
+ // to be kept open on click
+ AlertDialog d = (AlertDialog) getDialog();
+ Button defaultsButton = d.getButton(DialogInterface.BUTTON_NEUTRAL);
+ defaultsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mSeekBar.setProgress(intensityToPercent(VibratorHW.getDefaultIntensity()));
+ }
+ });
+ }
+
+ @Override
+ protected void onDialogClosed(boolean positiveResult) {
+ super.onDialogClosed(positiveResult);
+
+ if (positiveResult) {
+ // Store percent value in SharedPreferences object
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
+ prefs.edit().putInt(PREF_NAME, mSeekBar.getProgress()).commit();
+ } else {
+ VibratorHW.setIntensity(mOriginalValue);
+ }
+ }
+
+ public static boolean isSupported() {
+ try {
+ return VibratorHW.isSupported();
+ } catch (NoClassDefFoundError e) {
+ // Hardware abstraction framework isn't installed
+ return false;
+ }
+ }
+
+ public static void restore(Context context) {
+ if (!isSupported()) {
+ return;
+ }
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ int defaultValue = intensityToPercent(VibratorHW.getDefaultIntensity());
+ int percent = prefs.getInt(PREF_NAME, defaultValue);
+
+ VibratorHW.setIntensity(percentToIntensity(percent));
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ int warningThreshold = VibratorHW.getWarningThreshold();
+ boolean shouldWarn =
+ warningThreshold > 0 && progress >= intensityToPercent(warningThreshold);
+
+ if (mProgressDrawable != null) {
+ mProgressDrawable.setColorFilter(shouldWarn ? mRedFilter : null);
+ }
+ if (mProgressThumb != null) {
+ mProgressThumb.setColorFilter(shouldWarn ? mRedFilter : null);
+ }
+
+ VibratorHW.setIntensity(percentToIntensity(progress));
+ mValue.setText(String.format("%d%%", progress));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ // Do nothing here
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ Vibrator vib = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
+ vib.vibrate(200);
+ }
+
+ private static int intensityToPercent(int value) {
+ double maxValue = VibratorHW.getMaxIntensity();
+ double minValue = VibratorHW.getMinIntensity();
+ double percent = (value - minValue) * (100 / (maxValue - minValue));
+
+ if (percent > 100) {
+ percent = 100;
+ } else if (percent < 0) {
+ percent = 0;
+ }
+
+ return (int) percent;
+ }
+
+ private static int percentToIntensity(int percent) {
+ int maxValue = VibratorHW.getMaxIntensity();
+ int minValue = VibratorHW.getMinIntensity();
+ int value = Math.round((((maxValue - minValue) * percent) / 100) + minValue);
+
+ if (value > maxValue) {
+ value = maxValue;
+ } else if (value < minValue) {
+ value = minValue;
+ }
+
+ return value;
+ }
+}
diff --git a/src/com/android/settings/notification/OtherSoundSettings.java b/src/com/android/settings/notification/OtherSoundSettings.java
index 969ec90..a907a19 100644
--- a/src/com/android/settings/notification/OtherSoundSettings.java
+++ b/src/com/android/settings/notification/OtherSoundSettings.java
@@ -37,6 +37,7 @@ import com.android.internal.logging.MetricsLogger;
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;
@@ -66,6 +67,7 @@ public class OtherSoundSettings extends SettingsPreferenceFragment implements In
private static final String KEY_VIBRATE_ON_TOUCH = "vibrate_on_touch";
private static final String KEY_DOCK_AUDIO_MEDIA = "dock_audio_media";
private static final String KEY_EMERGENCY_TONE = "emergency_tone";
+ private static final String KEY_VIBRATION_INTENSITY = "vibration_intensity";
private static final SettingPref PREF_DIAL_PAD_TONES = new SettingPref(
TYPE_SYSTEM, KEY_DIAL_PAD_TONES, System.DTMF_TONE_WHEN_DIALING, DEFAULT_ON) {
@@ -111,6 +113,15 @@ public class OtherSoundSettings extends SettingsPreferenceFragment implements In
}
};
+ private static final SettingPref PREF_VIBRATION_INTENSITY = new SettingPref(
+ TYPE_SYSTEM, KEY_VIBRATION_INTENSITY, System.HAPTIC_FEEDBACK_ENABLED, DEFAULT_ON) {
+ @Override
+ public boolean isApplicable(Context context) {
+ return VibratorIntensity.isSupported();
+ }
+ };
+
+
private static final SettingPref PREF_DOCK_AUDIO_MEDIA = new SettingPref(
TYPE_GLOBAL, KEY_DOCK_AUDIO_MEDIA, Global.DOCK_AUDIO_MEDIA_ENABLED,
DEFAULT_DOCK_AUDIO_MEDIA, DOCK_AUDIO_MEDIA_DISABLED, DOCK_AUDIO_MEDIA_ENABLED) {
@@ -165,6 +176,7 @@ public class OtherSoundSettings extends SettingsPreferenceFragment implements In
PREF_VIBRATE_ON_TOUCH,
PREF_DOCK_AUDIO_MEDIA,
PREF_EMERGENCY_TONE,
+ PREF_VIBRATION_INTENSITY,
};
private final SettingsObserver mSettingsObserver = new SettingsObserver();