cmparts: Add display rotation settings

  * Original work by:
    - Robert Burns
    - Martin Brabham
    - David Van Tonder
    - Michael Bestas
    - Adnan Begovic

Change-Id: If1b4a45fb41b94136209acb47a5549a1b0c25143
diff --git a/proguard.flags b/proguard.flags
index dc38ff8..cf3010a 100644
--- a/proguard.flags
+++ b/proguard.flags
@@ -5,6 +5,7 @@
 
 -keep class org.cyanogenmod.cmparts.cmstats.*
 -keep class org.cyanogenmod.cmparts.contributors.*
+-keep class org.cyanogenmod.cmparts.hardware.*
 -keep class org.cyanogenmod.cmparts.input.*
 -keep class org.cyanogenmod.cmparts.livedisplay.*
 -keep class org.cyanogenmod.cmparts.notificationlight.*
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 83c8032..5f4dcd7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -491,4 +491,16 @@
     <string name="stats_collection_title">Stats collection</string>
     <string name="stats_collection_summary">When enabled, allows metrics collection</string>
 
+    <!-- Display : Rotation  -->
+    <string name="accelerometer_title">Auto-rotate screen</string>
+    <string name="display_rotation_title">Rotation settings</string>
+    <string name="display_rotation_disabled">Disabled</string>
+    <string name="display_rotation_unit">degrees</string>
+    <string name="display_lockscreen_rotation_title">Rotate lock screen</string>
+    <string name="display_rotation_category_title">Rotation modes</string>
+    <string name="display_rotation_0_title">0 degrees</string>
+    <string name="display_rotation_90_title">90 degrees</string>
+    <string name="display_rotation_180_title">180 degrees</string>
+    <string name="display_rotation_270_title">270 degrees</string>
+
 </resources>
diff --git a/res/xml/display_rotation.xml b/res/xml/display_rotation.xml
new file mode 100644
index 0000000..b36df56
--- /dev/null
+++ b/res/xml/display_rotation.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The CyanogenMod Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+        android:title="@string/display_rotation_title">
+
+    <SwitchPreference
+        android:key="accelerometer"
+        android:title="@string/accelerometer_title" />
+    <cyanogenmod.preference.CMSystemSettingSwitchPreference
+        android:key="lockscreen_rotation"
+        android:title="@string/display_lockscreen_rotation_title"
+        android:dependency="accelerometer"
+        android:defaultValue="false" />
+    <PreferenceCategory
+        android:key="display_rotation_category"
+        android:title="@string/display_rotation_category_title" />
+    <CheckBoxPreference
+        android:key="display_rotation_0"
+        android:title="@string/display_rotation_0_title"
+        android:layout="?android:attr/preferenceLayoutChild"
+        android:dependency="accelerometer" />
+    <CheckBoxPreference
+        android:key="display_rotation_90"
+        android:title="@string/display_rotation_90_title"
+        android:layout="?android:attr/preferenceLayoutChild"
+        android:dependency="accelerometer" />
+    <CheckBoxPreference
+        android:key="display_rotation_180"
+        android:title="@string/display_rotation_180_title"
+        android:layout="?android:attr/preferenceLayoutChild"
+        android:dependency="accelerometer" />
+    <CheckBoxPreference
+        android:key="display_rotation_270"
+        android:title="@string/display_rotation_270_title"
+        android:layout="?android:attr/preferenceLayoutChild"
+        android:dependency="accelerometer" />
+
+</PreferenceScreen>
diff --git a/res/xml/parts_catalog.xml b/res/xml/parts_catalog.xml
index 404d93f..94d6a7a 100644
--- a/res/xml/parts_catalog.xml
+++ b/res/xml/parts_catalog.xml
@@ -21,33 +21,37 @@
           android:title="@string/battery_light_title"
           android:fragment="org.cyanogenmod.cmparts.notificationlight.BatteryLightSettings" />
 
-    <part android:key="notification_lights"
-          android:title="@string/notification_light_title"
-          android:fragment="org.cyanogenmod.cmparts.notificationlight.NotificationLightSettings" />
+    <part android:key="button_settings"
+          android:title="@string/button_pref_title"
+          android:fragment="org.cyanogenmod.cmparts.input.ButtonSettings" />
+
+    <part android:key="contributors"
+          android:title="@string/contributors_cloud_fragment_title"
+          android:fragment="org.cyanogenmod.cmparts.contributors.ContributorsCloudFragment" />
 
     <part android:key="livedisplay"
           android:title="@*cyanogenmod.platform:string/live_display_title"
           android:summary="@string/live_display_summary"
           android:fragment="org.cyanogenmod.cmparts.livedisplay.LiveDisplay" />
 
+    <part android:key="notification_lights"
+          android:title="@string/notification_light_title"
+          android:fragment="org.cyanogenmod.cmparts.notificationlight.NotificationLightSettings" />
+
     <part android:key="privacy_settings"
           android:title="@string/privacy_settings_title"
           android:fragment="org.cyanogenmod.cmparts.PrivacySettings" />
 
-    <part android:key="button_settings"
-          android:title="@string/button_pref_title"
-          android:fragment="org.cyanogenmod.cmparts.input.ButtonSettings" />
-
     <part android:key="profiles_settings"
           android:title="@string/profiles_settings_title"
           android:fragment="org.cyanogenmod.cmparts.profiles.ProfilesSettings" />
 
+    <part android:key="rotation"
+          android:title="@string/display_rotation_title"
+          android:fragment="org.cyanogenmod.cmparts.hardware.DisplayRotation" />
+
     <part android:key="status_bar_settings"
           android:title="@string/status_bar_title"
           android:fragment="org.cyanogenmod.cmparts.statusbar.StatusBarSettings" />
 
-    <part android:key="contributors"
-          android:title="@string/contributors_cloud_fragment_title"
-          android:fragment="org.cyanogenmod.cmparts.contributors.ContributorsCloudFragment" />
-
 </parts-catalog>
diff --git a/src/org/cyanogenmod/cmparts/hardware/DisplayRotation.java b/src/org/cyanogenmod/cmparts/hardware/DisplayRotation.java
new file mode 100644
index 0000000..48a4ee8
--- /dev/null
+++ b/src/org/cyanogenmod/cmparts/hardware/DisplayRotation.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 The CyanogenMod Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.cyanogenmod.cmparts.hardware;
+
+import android.database.ContentObserver;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.Preference;
+import android.support.v7.preference.Preference.OnPreferenceChangeListener;
+import android.support.v7.preference.PreferenceScreen;
+import android.support.v14.preference.SwitchPreference;
+import android.provider.Settings;
+
+import com.android.internal.view.RotationPolicy;
+import org.cyanogenmod.cmparts.R;
+import org.cyanogenmod.cmparts.SettingsPreferenceFragment;
+
+public class DisplayRotation extends SettingsPreferenceFragment {
+    private static final String TAG = "DisplayRotation";
+
+    public static final String KEY_ACCELEROMETER = "accelerometer";
+    private static final String KEY_LOCKSCREEN_ROTATION = "lockscreen_rotation";
+    private static final String ROTATION_0_PREF = "display_rotation_0";
+    private static final String ROTATION_90_PREF = "display_rotation_90";
+    private static final String ROTATION_180_PREF = "display_rotation_180";
+    private static final String ROTATION_270_PREF = "display_rotation_270";
+
+    private SwitchPreference mAccelerometer;
+    private CheckBoxPreference mRotation0Pref;
+    private CheckBoxPreference mRotation90Pref;
+    private CheckBoxPreference mRotation180Pref;
+    private CheckBoxPreference mRotation270Pref;
+
+    public static final int ROTATION_0_MODE = 1;
+    public static final int ROTATION_90_MODE = 2;
+    public static final int ROTATION_180_MODE = 4;
+    public static final int ROTATION_270_MODE = 8;
+
+    private ContentObserver mAccelerometerRotationObserver = new ContentObserver(new Handler()) {
+        @Override
+        public void onChange(boolean selfChange) {
+            updateAccelerometerRotationSwitch();
+        }
+    };
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        addPreferencesFromResource(R.xml.display_rotation);
+
+        PreferenceScreen prefSet = getPreferenceScreen();
+
+        mAccelerometer = (SwitchPreference) findPreference(KEY_ACCELEROMETER);
+        mAccelerometer.setPersistent(false);
+
+        mRotation0Pref = (CheckBoxPreference) prefSet.findPreference(ROTATION_0_PREF);
+        mRotation90Pref = (CheckBoxPreference) prefSet.findPreference(ROTATION_90_PREF);
+        mRotation180Pref = (CheckBoxPreference) prefSet.findPreference(ROTATION_180_PREF);
+        mRotation270Pref = (CheckBoxPreference) prefSet.findPreference(ROTATION_270_PREF);
+
+        int mode = Settings.System.getInt(getContentResolver(),
+                Settings.System.ACCELEROMETER_ROTATION_ANGLES,
+                ROTATION_0_MODE | ROTATION_90_MODE | ROTATION_270_MODE);
+
+        mRotation0Pref.setChecked((mode & ROTATION_0_MODE) != 0);
+        mRotation90Pref.setChecked((mode & ROTATION_90_MODE) != 0);
+        mRotation180Pref.setChecked((mode & ROTATION_180_MODE) != 0);
+        mRotation270Pref.setChecked((mode & ROTATION_270_MODE) != 0);
+
+        boolean hasRotationLock = false;
+//        getResources().getBoolean(
+//                com.android.internal.R.bool.config_hasRotationLockSwitch);
+
+        if (hasRotationLock) {
+            // Disable accelerometer switch, but leave others enabled
+            mAccelerometer.setEnabled(false);
+            mRotation0Pref.setDependency(null);
+            mRotation90Pref.setDependency(null);
+            mRotation180Pref.setDependency(null);
+            mRotation270Pref.setDependency(null);
+        }
+
+        final SwitchPreference lockScreenRotation =
+                (SwitchPreference) findPreference(KEY_LOCKSCREEN_ROTATION);
+        boolean canRotateLockscreen = getResources().getBoolean(
+                com.android.internal.R.bool.config_enableLockScreenRotation);
+
+        if (lockScreenRotation != null && !canRotateLockscreen) {
+            getPreferenceScreen().removePreference(lockScreenRotation);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+
+        updateState();
+        getContentResolver().registerContentObserver(
+                Settings.System.getUriFor(Settings.System.ACCELEROMETER_ROTATION), true,
+                mAccelerometerRotationObserver);
+    }
+
+    @Override
+    public void onPause() {
+        super.onPause();
+
+        getContentResolver().unregisterContentObserver(mAccelerometerRotationObserver);
+    }
+
+    private void updateState() {
+        updateAccelerometerRotationSwitch();
+    }
+
+    private void updateAccelerometerRotationSwitch() {
+        mAccelerometer.setChecked(!RotationPolicy.isRotationLocked(getActivity()));
+    }
+
+    private int getRotationBitmask() {
+        int mode = 0;
+        if (mRotation0Pref.isChecked()) {
+            mode |= ROTATION_0_MODE;
+        }
+        if (mRotation90Pref.isChecked()) {
+            mode |= ROTATION_90_MODE;
+        }
+        if (mRotation180Pref.isChecked()) {
+            mode |= ROTATION_180_MODE;
+        }
+        if (mRotation270Pref.isChecked()) {
+            mode |= ROTATION_270_MODE;
+        }
+        return mode;
+    }
+
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference) {
+        if (preference == mAccelerometer) {
+            RotationPolicy.setRotationLockForAccessibility(getActivity(),
+                    !mAccelerometer.isChecked());
+        } else if (preference == mRotation0Pref ||
+                preference == mRotation90Pref ||
+                preference == mRotation180Pref ||
+                preference == mRotation270Pref) {
+            int mode = getRotationBitmask();
+            if (mode == 0) {
+                mode |= ROTATION_0_MODE;
+                mRotation0Pref.setChecked(true);
+            }
+            Settings.System.putInt(getActivity().getContentResolver(),
+                    Settings.System.ACCELEROMETER_ROTATION_ANGLES, mode);
+            return true;
+        }
+
+        return super.onPreferenceTreeClick(preference);
+    }
+}