[2/4] omnigears: custom brightness support

screenshots:
http://www.mediafire.com/view/c4o6i5hfcowj2/screenies#2v66f7gy03ffqvq

PS2:
whitespace cleanup

PS3:
disabled level split and remove
I hardly believe anyone will ever need this

PS4:
moved general brightness settings from display into our fragment
string changes

PS5:
rename and license fixup

PS6:
typo

PS7:
PS6 broke the build, the ' needs to be escaped.

Change-Id: I9bb9b2d07af0726b68d2abda22e12f3b922e4aaf
diff --git a/res/layout/auto_brightness_level_setup.xml b/res/layout/auto_brightness_level_setup.xml
new file mode 100644
index 0000000..3961367
--- /dev/null
+++ b/res/layout/auto_brightness_level_setup.xml
@@ -0,0 +1,61 @@
+<?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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:gravity="center_horizontal"
+        android:padding="8dip">
+
+    <TextView android:id="@+id/lux_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dip"
+            android:text="@string/auto_brightness_lux" />
+
+    <EditText android:id="@+id/lux"
+            android:singleLine="true"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="2dip"
+            android:numeric="integer" />
+
+    <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dip"
+            android:text="@string/auto_brightness_backlight" />
+
+    <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="2dip">
+
+        <SeekBar android:id="@+id/backlight"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1" />
+
+        <EditText android:id="@+id/backlight_input"
+                android:singleLine="true"
+                android:layout_width="80dip"
+                android:layout_height="wrap_content"
+                android:numeric="integer" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout/auto_brightness_list_item.xml b/res/layout/auto_brightness_list_item.xml
new file mode 100644
index 0000000..562cf08
--- /dev/null
+++ b/res/layout/auto_brightness_list_item.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2012-2013 The CyanogenMod Project
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:paddingStart="8dip"
+    android:paddingEnd="8dip"
+    android:descendantFocusability="blocksDescendants">
+
+    <TextView android:id="@+id/lux"
+        android:layout_width="50dp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical" />
+
+    <LinearLayout
+        android:orientation="vertical"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1">
+
+        <SeekBar android:id="@+id/backlight"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+        <TextView android:id="@+id/backlight_value"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="end"
+            android:layout_marginTop="-4dp"
+            style="?android:attr/textAppearanceSmall" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/res/layout/auto_brightness_split_dialog.xml b/res/layout/auto_brightness_split_dialog.xml
new file mode 100644
index 0000000..229f172
--- /dev/null
+++ b/res/layout/auto_brightness_split_dialog.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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:gravity="center_horizontal"
+        android:padding="8dip">
+
+    <TextView
+            android:id="@+id/split_label"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dip" />
+
+    <EditText android:id="@+id/split_position"
+            android:singleLine="true"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="2dip"
+            android:numeric="integer" />
+
+</LinearLayout>
diff --git a/res/layout/dialog_auto_brightness_levels.xml b/res/layout/dialog_auto_brightness_levels.xml
new file mode 100644
index 0000000..ecb03b2
--- /dev/null
+++ b/res/layout/dialog_auto_brightness_levels.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2010 Daniel Nilsson
+     Copyright (C) 2012 THe CyanogenMod Project
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License. -->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <LinearLayout
+        android:id="@+id/top_container"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:orientation="vertical"
+        android:divider="?android:attr/dividerHorizontal"
+        android:showDividers="end"
+        android:dividerPadding="0dip">
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:layoutDirection="locale">
+
+            <TextView
+                android:id="@+id/light_sensor_value"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:layout_gravity="center_vertical"
+                android:padding="8dip" />
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+    <ListView
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@id/top_container"
+        android:layout_alignParentBottom="true" />
+
+</RelativeLayout>
diff --git a/res/layout/dialog_manual_brightness.xml b/res/layout/dialog_manual_brightness.xml
new file mode 100644
index 0000000..e1069b1
--- /dev/null
+++ b/res/layout/dialog_manual_brightness.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2013 The OmniROM Project
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical"
+        android:gravity="center_horizontal"
+        android:padding="8dip">
+
+    <TextView
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="8dip"
+            android:text="@string/auto_brightness_backlight" />
+
+    <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="2dip">
+
+        <SeekBar android:id="@+id/backlight"
+                android:layout_width="0dip"
+                android:layout_height="wrap_content"
+                android:layout_weight="1" />
+
+        <EditText android:id="@+id/backlight_input"
+                android:singleLine="true"
+                android:layout_width="80dip"
+                android:layout_height="wrap_content"
+                android:numeric="integer" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/res/values/custom_arrays.xml b/res/values/custom_arrays.xml
index c4c7858..18eafe1 100644
--- a/res/values/custom_arrays.xml
+++ b/res/values/custom_arrays.xml
@@ -120,4 +120,21 @@
         <item>2500</item>
         <item>5000</item>
     </string-array>
+
+    <!-- Auto-brightness sensitivity -->
+    <string-array name="auto_brightness_sensitivity_entries" translatable="false">
+        <item>@string/auto_brightness_sensitivity_verylow</item>
+        <item>@string/auto_brightness_sensitivity_low</item>
+        <item>@string/auto_brightness_sensitivity_medium</item>
+        <item>@string/auto_brightness_sensitivity_high</item>
+        <item>@string/auto_brightness_sensitivity_veryhigh</item>
+    </string-array>
+
+    <string-array name="auto_brightness_sensitivity_values">
+        <item>150</item>
+        <item>125</item>
+        <item>100</item>
+        <item>50</item>
+        <item>25</item>
+    </string-array>
 </resources>
diff --git a/res/values/custom_strings.xml b/res/values/custom_strings.xml
index c8293c9..f49bc2e 100644
--- a/res/values/custom_strings.xml
+++ b/res/values/custom_strings.xml
@@ -139,6 +139,54 @@
     <string name="battery_light_medium_color_title">Charging</string>
     <string name="battery_light_full_color_title">Fully charged</string>
 
+    <!-- brightness settings -->
+    <string name="brightness_settings_title">Brightness setup</string>
+    <string name="screen_current_value">Current screen value: <xliff:g id="screen_level">%d</xliff:g></string>
+    <string name="button_current_value">Current button value: <xliff:g id="button_level">%d</xliff:g></string>
+
+    <string name="auto_brightness_sensitivity_title">Adjustment sensitivity</string>
+    <string name="auto_brightness_sensitivity_summary">Medium</string>
+    <string name="auto_brightness_sensitivity_verylow">Very low</string>
+    <string name="auto_brightness_sensitivity_low">Low</string>
+    <string name="auto_brightness_sensitivity_medium">Medium</string>
+    <string name="auto_brightness_sensitivity_high">High</string>
+    <string name="auto_brightness_sensitivity_veryhigh">Very high</string>
+
+    <string name="screen_brightness_category">Screen</string>
+    <string name="screen_auto_brightness">Automatic levels</string>
+    <string name="screen_auto_brighness_summary">Screen brightness levels for automatic mode</string>
+    <string name="button_auto_brightness">Automatic levels</string>
+    <string name="button_auto_brighness_summary">Button brightness levels for automatic mode</string>
+    <string name="button_brightness_category">Buttons</string>
+    <string name="button_no_brightness">Dark mode</string>
+    <string name="button_no_brightness_summary">Don\'t set button brightness</string>
+    <string name="button_link_brightness">Link to screen</string>
+    <string name="button_link_brightness_summary">Buttons brightness will use the same value as the screen</string>
+    <string name="button_manual_brightness">Manual level</string>
+    <string name="button_manual_brightness_summary">Button brightness level for manual mode</string>
+    <string name="dialog_manual_brightness_title">Button brightness</string>
+    <!-- Automatic brightness customization -->
+    <string name="auto_brightness_setup_title">Automatic brightness</string>
+    <string name="light_sensor_current_value">Current light sensor value: <xliff:g id="light_level">%d</xliff:g> lux</string>
+    <string name="auto_brightness_dialog_title">Automatic brightness levels</string>
+    <string name="auto_brightness_level_format"><xliff:g id="level">%1$d</xliff:g></string>
+    <string name="auto_brightness_last_level_format"><xliff:g id="level">%1$d</xliff:g>+</string>
+    <string name="auto_brightness_adjust_button">Adjust</string>
+    <string name="auto_brightness_close_button">Close</string>
+    <string name="auto_brightness_reset_button">Reset</string>
+    <string name="auto_brightness_split_dialog_title">Split brightness level</string>
+    <string name="auto_brightness_level_dialog_title">Brightness level</string>
+    <string name="auto_brightness_lux">Ambient brightness (lux)</string>
+    <string name="auto_brightness_backlight">Brightness</string>
+    <string name="auto_brightness_reset_dialog_title">Reset levels?</string>
+    <string name="auto_brightness_reset_confirmation">All brightness levels will be reset to their default settings.</string>
+    <string name="auto_brightness_split_lux_format">Split position (between <xliff:g id="min">%1$d</xliff:g> and <xliff:g id="max">%2$d</xliff:g> lux)</string>
+    <string name="auto_brightness_level_options">Light level options</string>
+    <string name="auto_brightness_menu_edit">Edit</string>
+    <string name="auto_brightness_menu_split">Split</string>
+    <string name="auto_brightness_menu_remove">Remove</string>
+    <string name="sensor_category">Sensor</string>
+
 </resources>
 
 
diff --git a/res/xml/brightness_settings.xml b/res/xml/brightness_settings.xml
new file mode 100644
index 0000000..7f92c11
--- /dev/null
+++ b/res/xml/brightness_settings.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--  Copyright (C) 2013 The OmniROM Project
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ -->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/brightness"
+        android:key="backlight_settings"
+        xmlns:settings="http://schemas.android.com/apk/res/com.android.settings">
+
+        <PreferenceCategory
+                android:key="screen_brightness_category"
+                android:title="@string/screen_brightness_category">
+
+                <com.android.settings.BrightnessPreference
+                        android:title="@string/brightness"
+                        android:persistent="false"/>
+
+                <Preference
+                        android:key="screen_auto_brightness"
+                        android:title="@string/screen_auto_brightness"
+                        android:summary="@string/screen_auto_brighness_summary"/>
+        </PreferenceCategory>
+
+        <PreferenceCategory
+                android:key="button_brightness_category"
+                android:title="@string/button_brightness_category">
+
+                <CheckBoxPreference
+                        android:key="button_no_brightness"
+                        android:title="@string/button_no_brightness"
+                        android:summary="@string/button_no_brightness_summary"/>
+                <CheckBoxPreference
+                        android:key="button_link_brightness"
+                        android:title="@string/button_link_brightness"
+                        android:summary="@string/button_link_brightness_summary"/>
+                <Preference
+                        android:key="button_auto_brightness"
+                        android:title="@string/button_auto_brightness"
+                        android:summary="@string/button_auto_brighness_summary"/>
+                <Preference
+                        android:key="button_manual_brightness"
+                        android:title="@string/button_manual_brightness"
+                        android:summary="@string/button_manual_brightness_summary"/>
+        </PreferenceCategory>
+
+        <PreferenceCategory
+                android:key="sensor_category"
+                android:title="@string/sensor_category">
+
+                <ListPreference
+                        android:key="auto_brightness_sensitivity"
+                        android:title="@string/auto_brightness_sensitivity_title"
+                        android:summary="@string/auto_brightness_sensitivity_summary"
+                        android:persistent="false"
+                        android:entries="@array/auto_brightness_sensitivity_entries"
+                        android:entryValues="@array/auto_brightness_sensitivity_values" />
+
+        </PreferenceCategory>
+</PreferenceScreen>
diff --git a/src/org/omnirom/omnigears/brightness/AutoBrightnessDialog.java b/src/org/omnirom/omnigears/brightness/AutoBrightnessDialog.java
new file mode 100644
index 0000000..801609f
--- /dev/null
+++ b/src/org/omnirom/omnigears/brightness/AutoBrightnessDialog.java
@@ -0,0 +1,836 @@
+/*
+ *  Copyright (C) 2013 The CyanogenMod Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.omnirom.omnigears.brightness;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Resources;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Bundle;
+import android.os.PowerManager;
+import android.os.IPowerManager;
+import android.os.ServiceManager;
+import android.provider.Settings;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.util.Spline;
+import android.view.ContextMenu;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ImageButton;
+import android.widget.ListView;
+import android.widget.PopupMenu;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import java.text.DecimalFormat;
+import java.text.DecimalFormatSymbols;
+import java.util.ArrayList;
+import java.util.Locale;
+
+import org.omnirom.omnigears.R;
+
+public class AutoBrightnessDialog extends AlertDialog
+        implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
+    private static final String TAG = "ScreenAutoBrightness";
+
+    private TextView mSensorLevel;
+    private ListView mConfigList;
+
+    private SensorManager mSensorManager;
+    private Sensor mLightSensor;
+
+    private static class SettingRow {
+        int lux;
+        int backlight;
+        public SettingRow(int lux, int backlight) {
+            this.lux = lux;
+            this.backlight = backlight;
+        }
+    };
+
+    private SettingRowAdapter mAdapter;
+    private int mMinLevel;
+    private boolean mIsDefault;
+
+    private AlertDialog mSetupDialog;
+    private AlertDialog mSplitDialog;
+
+    private boolean mAllowLuxEdit;
+    private String mSettingsValues;
+    private boolean mScreenMode;
+    private IPowerManager mPowerService;
+    private int mCurrentButtonBrightness;
+    private boolean mAllowLevelChange = false;
+
+    private SensorEventListener mLightSensorListener = new SensorEventListener() {
+        @Override
+        public void onSensorChanged(SensorEvent event) {
+            final int lux = Math.round(event.values[0]);
+            mSensorLevel.setText(getContext().getString(R.string.light_sensor_current_value, lux));
+        }
+
+        @Override
+        public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        }
+    };
+
+    public AutoBrightnessDialog(Context context, boolean screenMode) {
+        super(context);
+
+        mScreenMode = screenMode;
+        if (mScreenMode){
+            mAllowLuxEdit = true;
+            mSettingsValues = Settings.System.AUTO_BRIGHTNESS_SCREEN_BACKLIGHT;
+        } else {
+            mAllowLuxEdit = false;
+            mSettingsValues = Settings.System.AUTO_BRIGHTNESS_BUTTON_BACKLIGHT;
+        }
+    }
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        final Context context = getContext();
+        View view = getLayoutInflater().inflate(R.layout.dialog_auto_brightness_levels, null);
+        setView(view);
+        setTitle(R.string.auto_brightness_dialog_title);
+        setCancelable(true);
+
+        setButton(DialogInterface.BUTTON_POSITIVE, context.getString(android.R.string.ok), this);
+        setButton(DialogInterface.BUTTON_NEUTRAL,
+                context.getString(R.string.auto_brightness_reset_button), this);
+        setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(android.R.string.cancel), this);
+
+        super.onCreate(savedInstanceState);
+
+        mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
+        mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+
+        if (mScreenMode){
+            PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+            mMinLevel = pm.getMinimumAbsoluteScreenBrightness();
+        } else {
+            mMinLevel = 0;
+            mPowerService = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
+            // get the current level to reset to
+            try {
+                mCurrentButtonBrightness = mPowerService.getCurrentButtonBrightnessValue();
+            } catch(Exception e){
+            }
+        }
+
+        mSensorLevel = (TextView) view.findViewById(R.id.light_sensor_value);
+
+        mConfigList = (ListView) view.findViewById(android.R.id.list);
+        mAdapter = new SettingRowAdapter(context, new ArrayList<SettingRow>());
+        mConfigList.setAdapter(mAdapter);
+
+        if (mAllowLevelChange){
+            registerForContextMenu(mConfigList);
+        } else {
+            mConfigList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
+                public boolean onItemLongClick(AdapterView<?> parent, View view,int position, long id) {
+                    showSetup(position, null);
+                    return true;
+                }
+            });
+        }
+    }
+
+    @Override
+    protected void onStart() {
+        updateSettings(false);
+
+        super.onStart();
+
+        mSensorManager.registerListener(mLightSensorListener,
+                mLightSensor, SensorManager.SENSOR_DELAY_NORMAL);
+
+        Button neutralButton = getButton(DialogInterface.BUTTON_NEUTRAL);
+        neutralButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showResetConfirmation();
+            }
+        });
+    }
+
+    @Override
+    protected void onStop() {
+        super.onStop();
+        mSensorManager.unregisterListener(mLightSensorListener, mLightSensor);
+        if (mSetupDialog != null) {
+            mSetupDialog.dismiss();
+        }
+        if (mSplitDialog != null) {
+            mSplitDialog.dismiss();
+        }
+    }
+
+    @Override
+    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
+
+        menu.setHeaderTitle(R.string.auto_brightness_level_options);
+
+        menu.add(Menu.NONE, Menu.FIRST, 0, R.string.auto_brightness_menu_edit)
+                .setEnabled(!mAdapter.isLastItem(info.position));
+
+        if (mAllowLuxEdit && mAllowLevelChange){
+            menu.add(Menu.NONE, Menu.FIRST + 1, 1, R.string.auto_brightness_menu_split)
+                .setEnabled(mAdapter.canSplitRow(info.position));
+            menu.add(Menu.NONE, Menu.FIRST + 2, 2, R.string.auto_brightness_menu_remove)
+                .setEnabled(mAdapter.getCount() > 1);
+        }
+    }
+
+    @Override
+    public boolean onMenuItemSelected(int featureId, MenuItem item) {
+        AdapterView.AdapterContextMenuInfo info =
+                (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
+        int position = info.position;
+
+        switch (item.getItemId() - Menu.FIRST) {
+            case 0:
+                showSetup(position, null);
+                return true;
+            case 1:
+                showSplitDialog(position, null);
+                break;
+            case 2:
+                mAdapter.removeRow(position);
+                return true;
+        }
+
+        return false;
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        if (which == DialogInterface.BUTTON_POSITIVE) {
+            putSettings();
+        } else if (which == DialogInterface.BUTTON_NEGATIVE) {
+            cancel();
+        }
+    }
+
+    @Override
+    public void onDismiss(DialogInterface dialog) {
+        if (dialog == mSetupDialog) {
+            mSetupDialog = null;
+        } else if (dialog == mSplitDialog) {
+            mSplitDialog = null;
+        }
+    }
+
+    private void updateSettings(boolean forceDefault) {
+        int[] lux = null, values = null;
+
+        if (!forceDefault) {
+            lux = fetchItems(Settings.System.AUTO_BRIGHTNESS_LUX);
+            values = fetchItems(mSettingsValues);
+        }
+
+        if (lux != null && values != null && lux.length != values.length - 1) {
+            Log.e(TAG, "Found invalid backlight settings, ignoring");
+            values = null;
+        }
+
+        if (lux == null || values == null) {
+            final Resources res = getContext().getResources();
+            lux = res.getIntArray(com.android.internal.R.array.config_autoBrightnessLevels);
+            if (mScreenMode){
+                values = res.getIntArray(com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
+            } else {
+                values = res.getIntArray(com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
+            }
+            mIsDefault = true;
+        } else {
+            mIsDefault = false;
+        }
+
+        mAdapter.initFromSettings(lux, values);
+    }
+
+    private void showSetup(int position, Bundle state) {
+        if (mSetupDialog != null && mSetupDialog.isShowing()) {
+            return;
+        }
+
+        mSetupDialog = new RowSetupDialog(getContext(), position);
+        mSetupDialog.setOnDismissListener(this);
+        mSetupDialog.show();
+    }
+
+    private void showSplitDialog(final int position, Bundle state) {
+        if (mSplitDialog != null && mSplitDialog.isShowing()) {
+            return;
+        }
+
+        mSplitDialog = new RowSplitDialog(getContext(), position);
+        mSplitDialog.setOnDismissListener(this);
+        mSplitDialog.show();
+    }
+
+    private void showResetConfirmation() {
+        final AlertDialog d = new AlertDialog.Builder(getContext())
+            .setTitle(R.string.auto_brightness_reset_dialog_title)
+            .setCancelable(true)
+            .setMessage(R.string.auto_brightness_reset_confirmation)
+            .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface d, int which) {
+                    updateSettings(true);
+                }
+            })
+            .setNegativeButton(R.string.cancel, null)
+            .create();
+
+        d.show();
+    }
+
+    private void putSettings() {
+        int[] lux = null, values = null;
+
+        if (!mIsDefault) {
+            lux = mAdapter.getLuxValues();
+            values = mAdapter.getBacklightValues();
+        }
+
+        if (mAllowLuxEdit){
+            putItems(Settings.System.AUTO_BRIGHTNESS_LUX, lux);
+        }
+        putItems(mSettingsValues, values);
+    }
+
+    private int[] fetchItems(String setting) {
+        String value = Settings.System.getString(getContext().getContentResolver(), setting);
+        if (value != null) {
+            String[] values = value.split(",");
+            if (values != null && values.length != 0) {
+                int[] result = new int[values.length];
+                int i;
+
+                for (i = 0; i < values.length; i++) {
+                    try {
+                        result[i] = Integer.valueOf(values[i]);
+                    } catch (NumberFormatException e) {
+                        break;
+                    }
+                }
+                if (i == values.length) {
+                    return result;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private void putItems(String setting, int[] values) {
+        String value = null;
+        if (values != null) {
+            final StringBuilder builder = new StringBuilder();
+            for (int i = 0; i < values.length; i++) {
+                if (i > 0) {
+                    builder.append(",");
+                }
+                builder.append(values[i]);
+            }
+            value = builder.toString();
+        }
+        Settings.System.putString(getContext().getContentResolver(), setting, value);
+    }
+
+    private class RowSetupDialog extends AlertDialog implements DialogInterface.OnClickListener {
+
+        private EditText mLuxInput;
+        private SeekBar mBacklightBar;
+        private EditText mBacklightInput;
+        private TextView mLuxText;
+
+        private int mPosition;
+
+        public RowSetupDialog(Context context, int position) {
+            super(context);
+            mPosition = position;
+        }
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            final View v = getLayoutInflater().inflate(R.layout.auto_brightness_level_setup, null);
+            final Context context = getContext();
+
+            mLuxInput = (EditText) v.findViewById(R.id.lux);
+            mLuxText = (TextView) v.findViewById(R.id.lux_text);
+
+            if (!mAllowLuxEdit){
+                mLuxInput.setVisibility(View.GONE);
+                mLuxText.setVisibility(View.GONE);
+            }
+            mBacklightBar = (SeekBar) v.findViewById(R.id.backlight);
+            mBacklightInput = (EditText) v.findViewById(R.id.backlight_input);
+
+            setTitle(R.string.auto_brightness_level_dialog_title);
+            setCancelable(true);
+            setView(v);
+
+            mBacklightBar.setMax(brightnessToProgress(PowerManager.BRIGHTNESS_ON));
+            initListeners();
+            initFromPosition();
+
+            setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.ok), this);
+            setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel), this);
+
+            super.onCreate(savedInstanceState);
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            if (which == DialogInterface.BUTTON_POSITIVE) {
+                try {
+                    int newLux = Integer.valueOf(mLuxInput.getText().toString());
+                    int newBacklight = Integer.valueOf(mBacklightInput.getText().toString());
+                    mAdapter.setValuesForRow(mPosition, newLux, newBacklight);
+                } catch (NumberFormatException e) {
+                    Log.d(TAG, "NumberFormatException " + e);
+                }
+            }
+        }
+
+        private void initFromPosition() {
+            final SettingRow row = mAdapter.getItem(mPosition);
+
+            mLuxInput.setText(String.valueOf(row.lux));
+            mBacklightBar.setProgress(brightnessToProgress(row.backlight));
+            mBacklightInput.setText(String.valueOf(row.backlight));
+        }
+
+        private void initListeners() {
+            mBacklightBar.setOnSeekBarChangeListener(new BrightnessSeekBarChangeListener() {
+                @Override
+                protected int getPosition(SeekBar seekBar) {
+                    return mPosition;
+                }
+
+                @Override
+                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                    super.onProgressChanged(seekBar, progress, fromUser);
+
+                    int brightness = progressToBrightness(seekBar.getProgress());
+                    mBacklightInput.setText(String.valueOf(brightness));
+                }
+            });
+
+            mBacklightInput.addTextChangedListener(new TextWatcher() {
+                @Override
+                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+                }
+                @Override
+                public void onTextChanged(CharSequence s, int start, int before, int count) {
+                }
+                @Override
+                public void afterTextChanged(Editable s) {
+                    boolean ok = false;
+                    try {
+                        int minValue = mPosition == 0
+                                ? mMinLevel
+                                : mAdapter.getItem(mPosition - 1).backlight;
+                        int maxValue = mAdapter.isLastItem(mPosition)
+                                ? PowerManager.BRIGHTNESS_ON
+                                : mAdapter.getItem(mPosition + 1).backlight;
+                        int newBrightness = Integer.valueOf(s.toString());
+
+                        if (newBrightness >= minValue && newBrightness <= maxValue) {
+                            ok = true;
+                            mBacklightBar.setProgress(brightnessToProgress(newBrightness));
+                        }
+                    } catch (NumberFormatException e) {
+                        //ignored, ok is false anyway
+                    }
+
+                    Button okButton = mSetupDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+                    if (okButton != null) {
+                        okButton.setEnabled(ok);
+                    }
+                }
+            });
+        }
+    }
+
+    private class RowSplitDialog extends AlertDialog implements DialogInterface.OnClickListener {
+
+        private TextView mLabel;
+        private EditText mValue;
+
+        private int mPosition;
+        private int mMinLux, mMaxLux;
+
+        public RowSplitDialog(Context context, int position) {
+            super(context);
+            mPosition = position;
+        }
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            final View v = getLayoutInflater().inflate(R.layout.auto_brightness_split_dialog, null);
+            final Context context = getContext();
+
+            mLabel = (TextView) v.findViewById(R.id.split_label);
+            mValue = (EditText) v.findViewById(R.id.split_position);
+
+            setTitle(R.string.auto_brightness_split_dialog_title);
+            setCancelable(true);
+            setView(v);
+
+            initValues();
+            initListener();
+
+            setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.ok), this);
+            setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel), this);
+
+            super.onCreate(savedInstanceState);
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            if (which == DialogInterface.BUTTON_POSITIVE) {
+                int splitLux = Integer.valueOf(mValue.getText().toString());
+                mAdapter.splitRow(mPosition, splitLux);
+            }
+        }
+
+        private void initValues() {
+            final SettingRow row = mAdapter.getItem(mPosition);
+
+            mMinLux = row.lux + 1;
+            mMaxLux = mAdapter.isLastItem(mPosition) ? 0 : mAdapter.getItem(mPosition + 1).lux - 1;
+
+            mLabel.setText(getContext().getString(R.string.auto_brightness_split_lux_format,
+                    mMinLux, mMaxLux));
+            mValue.setText(String.valueOf(mMinLux));
+        }
+
+        private void initListener() {
+            mValue.addTextChangedListener(new TextWatcher() {
+                @Override
+                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+                }
+                @Override
+                public void onTextChanged(CharSequence s, int start, int before, int count) {
+                }
+                @Override
+                public void afterTextChanged(Editable s) {
+                    boolean ok = false;
+                    try {
+                        int newLux = Integer.valueOf(s.toString());
+                        ok = newLux >= mMinLux && newLux <= mMaxLux;
+                    } catch (NumberFormatException e) {
+                        //ignored, ok is false anyway
+                    }
+                    Button okButton = getButton(DialogInterface.BUTTON_POSITIVE);
+                    if (okButton != null) {
+                        okButton.setEnabled(ok);
+                    }
+                }
+            });
+        }
+    }
+
+    private class SettingRowAdapter extends ArrayAdapter<SettingRow> {
+        public SettingRowAdapter(Context context, ArrayList<SettingRow> rows) {
+            super(context, 0, rows);
+            setNotifyOnChange(false);
+        }
+
+        private boolean isLastItem(int position) {
+            return position == getCount() - 1;
+        }
+
+        public boolean canSplitRow(int position) {
+            if (isLastItem(position)) {
+                return false;
+            }
+
+            SettingRow row = getItem(position);
+            SettingRow next = getItem(position + 1);
+            return next.lux > (row.lux + 1);
+        }
+
+        public void initFromSettings(int[] lux, int[] values) {
+            ArrayList<SettingRow> settings = new ArrayList<SettingRow>(values.length);
+            for (int i = 0; i < lux.length; i++) {
+                settings.add(new SettingRow(i == 0 ? 0 : lux[i - 1], values[i]));
+            }
+            settings.add(new SettingRow(lux[lux.length - 1], values[values.length - 1]));
+
+            clear();
+            addAll(settings);
+            notifyDataSetChanged();
+        }
+
+        public int[] getLuxValues() {
+            int count = getCount();
+            int[] lux = new int[count - 1];
+
+            for (int i = 1; i < count; i++) {
+                lux[i - 1] = getItem(i).lux;
+            }
+
+            return lux;
+        }
+
+        public int[] getBacklightValues() {
+            int count = getCount();
+            int[] values = new int[count];
+
+            for (int i = 0; i < count; i++) {
+                values[i] = getItem(i).backlight;
+            }
+            return values;
+        }
+
+        public void splitRow(int position, int splitLux) {
+            if (!canSplitRow(position)) {
+                return;
+            }
+
+            ArrayList<SettingRow> rows = new ArrayList<SettingRow>();
+            for (int i = 0; i <= position; i++) {
+                rows.add(getItem(i));
+            }
+
+            SettingRow lastRow = getItem(position);
+            rows.add(new SettingRow(splitLux, lastRow.backlight));
+
+            for (int i = position + 1; i < getCount(); i++) {
+                rows.add(getItem(i));
+            }
+
+            clear();
+            addAll(rows);
+            sanitizeValuesAndNotify();
+        }
+
+        public void removeRow(int position) {
+            if (getCount() <= 1) {
+                return;
+            }
+
+            remove(getItem(position));
+            sanitizeValuesAndNotify();
+        }
+
+        public void setValuesForRow(final int position, int newLux, int newBacklight) {
+            final SettingRow row = getItem(position);
+            boolean changed = false;
+
+            if (isLastItem(position)) {
+                return;
+            }
+
+            if (row.lux != newLux){
+                row.lux = newLux;
+                changed = true;
+            }
+            if (row.backlight != newBacklight){
+                row.backlight = newBacklight;
+                changed = true;
+            }
+
+            if (changed){
+                sanitizeValuesAndNotify();
+            }
+        }
+
+        public void sanitizeValuesAndNotify() {
+            final int count = getCount();
+
+            getItem(0).lux = 0;
+            for (int i = 1; i < count; i++) {
+                SettingRow lastRow = getItem(i - 1);
+                SettingRow thisRow = getItem(i);
+
+                thisRow.lux = Math.max(lastRow.lux + 1, thisRow.lux);
+                thisRow.backlight = Math.max(lastRow.backlight, thisRow.backlight);
+            }
+
+            mIsDefault = false;
+            mAdapter.notifyDataSetChanged();
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final Holder holder;
+
+            if (convertView == null) {
+                convertView = getLayoutInflater().inflate(
+                        R.layout.auto_brightness_list_item, parent, false);
+                holder = new Holder();
+                holder.lux = (TextView) convertView.findViewById(R.id.lux);
+                holder.backlight = (SeekBar) convertView.findViewById(R.id.backlight);
+                holder.backlightValue = (TextView) convertView.findViewById(R.id.backlight_value);
+                convertView.setTag(holder);
+
+                holder.backlight.setMax(brightnessToProgress(PowerManager.BRIGHTNESS_ON));
+                holder.backlight.setOnSeekBarChangeListener(new BrightnessSeekBarChangeListener() {
+                    @Override
+                    protected int getPosition(SeekBar seekBar) {
+                        return (Integer) seekBar.getTag();
+                    }
+
+                    @Override
+                    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                        super.onProgressChanged(seekBar, progress, fromUser);
+
+                        if (fromUser) {
+                            int pos = getPosition(seekBar);
+                            progress = seekBar.getProgress();
+                            getItem(pos).backlight = progressToBrightness(progress);
+                            mIsDefault = false;
+                        }
+
+                        holder.updateBacklight();
+                    }
+                });
+            } else {
+                holder = (Holder) convertView.getTag();
+            }
+
+            SettingRow row = (SettingRow) getItem(position);
+
+            final int resId = isLastItem(position)
+                    ? R.string.auto_brightness_last_level_format
+                    : R.string.auto_brightness_level_format;
+
+            holder.lux.setText(getContext().getString(resId, row.lux));
+
+            holder.backlight.setTag(position);
+            holder.backlight.setProgress(brightnessToProgress(row.backlight));
+            holder.updateBacklight();
+
+            return convertView;
+        }
+
+        private class Holder {
+            TextView lux;
+            SeekBar backlight;
+            TextView backlightValue;
+
+            public void updateBacklight() {
+                backlightValue.setText(String.valueOf(progressToBrightness(backlight.getProgress())));
+            }
+        };
+    };
+
+    private int brightnessToProgress(int brightness) {
+        brightness -= mMinLevel;
+        return brightness * 100;
+    }
+
+    private int progressToBrightness(int progress) {
+        int brightness = progress / 100;
+        return brightness + mMinLevel;
+    }
+
+    private abstract class BrightnessSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
+        private boolean mIsDragging = false;
+
+        private void updateBrightness(float brightness) {
+            if (mScreenMode){
+                final Window window = getWindow();
+                final WindowManager.LayoutParams params = window.getAttributes();
+                params.screenBrightness = brightness;
+                window.setAttributes(params);
+            } else {
+                try {
+                    mPowerService.setButtonBrightness((int)brightness);
+                } catch(Exception e){
+                }
+            }
+        }
+
+        protected abstract int getPosition(SeekBar seekBar);
+
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            int pos = getPosition(seekBar);
+            if (fromUser) {
+                int minValue = pos == 0
+                        ? 0
+                        : brightnessToProgress(mAdapter.getItem(pos - 1).backlight);
+                int maxValue = mAdapter.isLastItem(pos)
+                        ? seekBar.getMax()
+                        : brightnessToProgress(mAdapter.getItem(pos + 1).backlight);
+
+                if (progress < minValue) {
+                    seekBar.setProgress(minValue);
+                    progress = minValue;
+                } else if (progress > maxValue) {
+                    seekBar.setProgress(maxValue);
+                    progress = maxValue;
+                }
+            }
+
+            if (mIsDragging) {
+                float brightness = progressToBrightness(progress);
+                if (mScreenMode){
+                    updateBrightness(brightness / PowerManager.BRIGHTNESS_ON);
+                } else {
+                    updateBrightness(brightness);
+                }
+            }
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+            float brightness = progressToBrightness(seekBar.getProgress());
+            if (mScreenMode){
+                updateBrightness(brightness / PowerManager.BRIGHTNESS_ON);
+            } else {
+                updateBrightness(brightness);
+            }
+
+            mIsDragging = true;
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            if (mScreenMode){
+                updateBrightness(WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE);
+            } else {
+                updateBrightness(mCurrentButtonBrightness);
+            }
+
+            mIsDragging = false;
+        }
+    };
+}
diff --git a/src/org/omnirom/omnigears/brightness/BrightnessSettings.java b/src/org/omnirom/omnigears/brightness/BrightnessSettings.java
new file mode 100644
index 0000000..568742a
--- /dev/null
+++ b/src/org/omnirom/omnigears/brightness/BrightnessSettings.java
@@ -0,0 +1,343 @@
+/*
+ *  Copyright (C) 2013 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package org.omnirom.omnigears.brightness;
+
+import com.android.settings.SettingsPreferenceFragment;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.IPowerManager;
+import android.os.ServiceManager;
+import android.preference.Preference;
+import android.preference.PreferenceGroup;
+import android.preference.PreferenceScreen;
+import android.preference.ListPreference;
+import android.preference.CheckBoxPreference;
+import android.preference.PreferenceCategory;
+import android.provider.Settings;
+import android.view.View;
+import android.util.Log;
+import android.app.AlertDialog;
+import android.text.TextWatcher;
+import android.text.Editable;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.SeekBar;
+
+import org.omnirom.omnigears.R;
+
+public class BrightnessSettings extends SettingsPreferenceFragment implements
+        Preference.OnPreferenceChangeListener {
+    private static final String TAG = "BrightnessSettings";
+
+    private static final String KEY_AUTOMATIC_SENSITIVITY = "auto_brightness_sensitivity";
+    private static final String KEY_BUTTON_BRIGHTNESS_CATEGORY = "button_brightness_category";
+    private static final String KEY_BUTTON_NO_BRIGHTNESS = "button_no_brightness";
+    private static final String KEY_BUTTON_LINK_BRIGHTNESS = "button_link_brightness";
+    private static final String KEY_SCREEN_AUTO_BRIGHTNESS = "screen_auto_brightness";
+    private static final String KEY_BUTTON_AUTO_BRIGHTNESS = "button_auto_brightness";
+    private static final String KEY_BUTTON_MANUAL_BRIGHTNESS = "button_manual_brightness";
+
+    private ListPreference mAutomaticSensitivity;
+    private CheckBoxPreference mNoButtonBrightness;
+    private CheckBoxPreference mLinkButtonBrightness;
+    private Preference mAutomaticScreenBrightness;
+    private Preference mAutomaticButtonBrightness;
+    private Preference mManualButtonBrightness;
+    private AutoBrightnessDialog mScreenBrightnessDialog;
+    private AutoBrightnessDialog mButtonBrightnessDialog;
+    private ManualButtonBrightnessDialog mManualBrightnessDialog;
+    private boolean mButtonBrightnessSupport;
+    private IPowerManager mPowerService;
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.brightness_settings);
+
+        PreferenceScreen prefSet = getPreferenceScreen();
+        ContentResolver resolver = getActivity().getContentResolver();
+
+        mButtonBrightnessSupport = getResources().getBoolean(com.android.internal.R.bool.config_button_brightness_support);
+
+        mAutomaticSensitivity = (ListPreference) findPreference(KEY_AUTOMATIC_SENSITIVITY);
+        float currentSensitivity = Settings.System.getFloat(resolver,
+            Settings.System.AUTO_BRIGHTNESS_RESPONSIVENESS, 1.0f);
+                    
+        int currentSensitivityInt = (int) (currentSensitivity * 100);
+        mAutomaticSensitivity.setValue(String.valueOf(currentSensitivityInt));
+        updateAutomaticSensityDescription(currentSensitivityInt);
+        mAutomaticSensitivity.setOnPreferenceChangeListener(this);
+
+        mAutomaticScreenBrightness = (Preference) findPreference(KEY_SCREEN_AUTO_BRIGHTNESS);
+
+        if (!mButtonBrightnessSupport){
+            removePreference(KEY_BUTTON_BRIGHTNESS_CATEGORY);
+        } else {
+            mNoButtonBrightness = (CheckBoxPreference) findPreference(KEY_BUTTON_NO_BRIGHTNESS);
+            mNoButtonBrightness.setChecked(Settings.System.getInt(resolver,
+                    Settings.System.CUSTOM_BUTTON_DISABLE_BRIGHTNESS, 0) != 0);
+
+            mLinkButtonBrightness = (CheckBoxPreference) findPreference(KEY_BUTTON_LINK_BRIGHTNESS);
+            mLinkButtonBrightness.setChecked(Settings.System.getInt(resolver,
+                    Settings.System.CUSTOM_BUTTON_USE_SCREEN_BRIGHTNESS, 0) != 0);
+
+            mAutomaticButtonBrightness = (Preference) findPreference(KEY_BUTTON_AUTO_BRIGHTNESS);
+            mManualButtonBrightness = (Preference) findPreference(KEY_BUTTON_MANUAL_BRIGHTNESS);
+
+            mPowerService = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        if (mScreenBrightnessDialog != null) {
+            mScreenBrightnessDialog.dismiss();
+        }
+        if (mButtonBrightnessDialog != null) {
+            mButtonBrightnessDialog.dismiss();
+        }
+        if (mManualBrightnessDialog != null) {
+            mManualBrightnessDialog.dismiss();
+        }
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+        if (preference == mAutomaticScreenBrightness) {
+            showScreenAutoBrightnessDialog();
+        } else if (preference == mAutomaticButtonBrightness) {
+            showButtonAutoBrightnessDialog();
+        } else if (preference == mManualButtonBrightness) {
+            showButtonManualBrightnessDialog();
+        } else if (preference == mNoButtonBrightness) {
+            boolean checked = ((CheckBoxPreference)preference).isChecked();
+            Settings.System.putInt(getActivity().getContentResolver(),
+                    Settings.System.CUSTOM_BUTTON_DISABLE_BRIGHTNESS, checked ? 1:0);
+        } else if (preference == mLinkButtonBrightness) {
+            boolean checked = ((CheckBoxPreference)preference).isChecked();
+            Settings.System.putInt(getActivity().getContentResolver(),
+                    Settings.System.CUSTOM_BUTTON_USE_SCREEN_BRIGHTNESS, checked ? 1:0);
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean onPreferenceChange(Preference preference, Object objValue) {
+        final String key = preference.getKey();
+
+        if (KEY_AUTOMATIC_SENSITIVITY.equals(key)) {
+            int value = Integer.parseInt((String) objValue);
+            float sensitivity = 0.01f * value;
+
+            Settings.System.putFloat(getContentResolver(),
+                        Settings.System.AUTO_BRIGHTNESS_RESPONSIVENESS, sensitivity);
+
+            updateAutomaticSensityDescription(value);
+        } else {
+            return false;
+        }
+        return true;
+    }
+
+    private void updateAutomaticSensityDescription(int value) {
+        String[] sensitivityValues = getResources().getStringArray(
+            R.array.auto_brightness_sensitivity_values);
+
+        for (int i = 0; i < sensitivityValues.length; i++) {
+            if (sensitivityValues[i].equals(String.valueOf(value))) {
+                mAutomaticSensitivity.setSummary(getResources().getStringArray(
+                    R.array.auto_brightness_sensitivity_entries)[i]);
+                break;
+            }
+        }
+    }
+
+    private void showScreenAutoBrightnessDialog() {
+        if (mScreenBrightnessDialog != null && mScreenBrightnessDialog.isShowing()) {
+            return;
+        }
+
+        mScreenBrightnessDialog = new AutoBrightnessDialog(getActivity(), true);
+        mScreenBrightnessDialog.show();
+    }
+
+    private void showButtonAutoBrightnessDialog() {
+        if (mButtonBrightnessDialog != null && mButtonBrightnessDialog.isShowing()) {
+            return;
+        }
+
+        mButtonBrightnessDialog = new AutoBrightnessDialog(getActivity(), false);
+        mButtonBrightnessDialog.show();
+    }
+
+    private void showButtonManualBrightnessDialog() {
+        if (mManualBrightnessDialog != null && mManualBrightnessDialog.isShowing()) {
+            return;
+        }
+
+        mManualBrightnessDialog = new ManualButtonBrightnessDialog(getActivity());
+        mManualBrightnessDialog.show();
+    }
+
+    private class ManualButtonBrightnessDialog extends AlertDialog implements DialogInterface.OnClickListener {
+
+        private SeekBar mBacklightBar;
+        private EditText mBacklightInput;
+        private int mCurrentBrightness;
+        private boolean mIsDragging = false;
+
+        public ManualButtonBrightnessDialog(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            final View v = getLayoutInflater().inflate(R.layout.dialog_manual_brightness, null);
+            final Context context = getContext();
+
+            mBacklightBar = (SeekBar) v.findViewById(R.id.backlight);
+            mBacklightInput = (EditText) v.findViewById(R.id.backlight_input);
+
+            setTitle(R.string.dialog_manual_brightness_title);
+            setCancelable(true);
+            setView(v);
+
+            try {
+                mCurrentBrightness = mPowerService.getCurrentButtonBrightnessValue();
+            } catch(Exception e){
+            }
+
+            mBacklightBar.setMax(brightnessToProgress(PowerManager.BRIGHTNESS_ON));
+            initListeners();
+            init();
+
+            setButton(DialogInterface.BUTTON_POSITIVE, context.getString(R.string.ok), this);
+            setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel), this);
+
+            super.onCreate(savedInstanceState);
+        }
+
+        private int brightnessToProgress(int brightness) {
+            return brightness * 100;
+        }
+
+        private int progressToBrightness(int progress) {
+            int brightness = progress / 100;
+            return brightness;
+        }
+
+        @Override
+        public void onClick(DialogInterface dialog, int which) {
+            if (which == DialogInterface.BUTTON_POSITIVE) {
+                try {
+                    int newBacklight = Integer.valueOf(mBacklightInput.getText().toString());
+                    Settings.System.putInt(getActivity().getContentResolver(),
+                            Settings.System.CUSTOM_BUTTON_BRIGHTNESS, newBacklight);
+                } catch (NumberFormatException e) {
+                    Log.d(TAG, "NumberFormatException " + e);
+                }
+            }
+        }
+
+        private void init() {
+            int currentValue = Settings.System.getInt(getActivity().getContentResolver(),
+                            Settings.System.CUSTOM_BUTTON_BRIGHTNESS, 100);
+
+            mBacklightBar.setProgress(brightnessToProgress(currentValue));
+            mBacklightInput.setText(String.valueOf(currentValue));
+        }
+
+        private void initListeners() {
+            mBacklightBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+                @Override
+                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+                    if (mIsDragging) {
+                        int brightness = progressToBrightness(seekBar.getProgress());
+                        mBacklightInput.setText(String.valueOf(brightness));
+                        try {
+                            mPowerService.setButtonBrightness(brightness);
+                        } catch(Exception e){
+                        }
+                    }
+                }
+                @Override
+                public void onStartTrackingTouch(SeekBar seekBar) {
+                    int brightness = progressToBrightness(seekBar.getProgress());
+                    try {
+                        mPowerService.setButtonBrightness(brightness);
+                    } catch(Exception e){
+                    }
+                    mIsDragging = true;
+                }
+                @Override
+                public void onStopTrackingTouch(SeekBar seekBar) {
+                    try {
+                        mPowerService.setButtonBrightness(mCurrentBrightness);
+                    } catch(Exception e){
+                    }
+                    mIsDragging = false;
+                }
+            });
+
+            mBacklightInput.addTextChangedListener(new TextWatcher() {
+                @Override
+                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+                }
+                @Override
+                public void onTextChanged(CharSequence s, int start, int before, int count) {
+                }
+                @Override
+                public void afterTextChanged(Editable s) {
+                    boolean ok = false;
+                    try {
+                        int minValue = 0;
+                        int maxValue = PowerManager.BRIGHTNESS_ON;
+                        int newBrightness = Integer.valueOf(s.toString());
+
+                        if (newBrightness >= minValue && newBrightness <= maxValue) {
+                            ok = true;
+                            mBacklightBar.setProgress(brightnessToProgress(newBrightness));
+                        }
+                    } catch (NumberFormatException e) {
+                        //ignored, ok is false anyway
+                    }
+
+                    Button okButton = mManualBrightnessDialog.getButton(DialogInterface.BUTTON_POSITIVE);
+                    if (okButton != null) {
+                        okButton.setEnabled(ok);
+                    }
+                }
+            });
+        }
+    }
+}
+