sm8350-common: parts: Import DC Dimming and HBM Settings

* Implement DC Dimming preference
* Disable DC Dimming if it's not supported
* Implement HBM switch
* Adapt HBM and DC dimming settings to S style
* Define DC dimming and HBM nodes / keys in one place
* Declare exported flags in manifest
* Fix compilation for QPR1
* Fix compilation for Android 15
* Adapt to sm8350-common devices

Co-Authored-By: Nauval Rizky <enuma.alrizky@gmail.com>
Co-Authored-By: Adhitya Mohan <me@adhityamohan.in>
Co-Authored-By: TheScarastic <warabhishek@gmail.com>
Co-Authored-By: alibei <sebastiankotzias83@gmail.com>
Co-Authored-By: kamikaonashi <thorschi93@gmx.at>
This commit is contained in:
kamikaonashi 2025-01-04 22:14:41 +01:00 committed by DigiGoon
parent d623393e11
commit 675a14ba3e
31 changed files with 1673 additions and 1 deletions

View file

@ -113,6 +113,64 @@
android:icon="@drawable/ic_thermal" android:icon="@drawable/ic_thermal"
android:label="@string/thermal_title" android:label="@string/thermal_title"
android:exported="true" android:exported="true"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action
android:name="android.service.quicksettings.action.QS_TILE"/>
</intent-filter>
</service>
<service
android:name=".display.DcDimmingTileService"
android:exported="true"
android:icon="@drawable/ic_dc_tile"
android:label="@string/dc_dimming_enable_title"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter>
<action
android:name="android.service.quicksettings.action.QS_TILE"/>
</intent-filter>
</service>
<activity
android:name=".display.DcDimmingSettingsActivity"
android:label="@string/dc_dimming_enable_title"
android:exported="true"
android:theme="@style/Theme.SubSettingsBase">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
</intent-filter>
<meta-data
android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.display" />
<meta-data
android:name="com.android.settings.summary"
android:resource="@string/dc_dimming_enable_summary" />
</activity>
<activity
android:name=".hbm.HBMActivity"
android:label="@string/hbm_fragment_title"
android:exported="false"
android:theme="@style/Theme.SubSettingsBase">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
</intent-filter>
<meta-data
android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.display" />
<meta-data
android:name="com.android.settings.summary"
android:resource="@string/hbm_fragment_summary" />
</activity>
<activity
android:name=".hbm.HBMFragment" />
<service
android:name=".hbm.AutoHBMService"
android:exported="false" />
<service
android:name=".hbm.HBMModeTileService"
android:icon="@drawable/ic_hbm_tile"
android:label="@string/hbm_mode_title"
android:exported="true"
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"> android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
<intent-filter> <intent-filter>
<action <action

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018-2021 crDroid Android 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0" >
<path
android:fillColor="?android:attr/colorControlNormal"
android:pathData="M19,13H5V11H19V13Z" />
</vector>

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018-2021 crDroid Android 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0" >
<path
android:fillColor="?android:attr/colorControlNormal"
android:pathData="M38.0,26.0L26.0,26.0l0.0,12.0l-4.0,0.0L22.0,26.0L10.0,26.0l0.0,-4.0l12.0,0.0L22.0,10.0l4.0,0.0l0.0,12.0l12.0,0.0l0.0,4.0z" />
</vector>

View file

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2018-2021 crDroid Android 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24.0dp"
android:height="24.0dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0" >
<path
android:fillColor="?android:attr/colorControlNormal"
android:pathData="M12.5,8C9.85,8 7.45,9 5.6,10.6L2,7V16H11L7.38,12.38C8.77,11.22 10.54,10.5 12.5,10.5C16.04,10.5 19.05,12.81 20.1,16L22.47,15.22C21.08,11.03 17.15,8 12.5,8Z" />
</vector>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M14,8.5A1.5,1.5 0 0,0 12.5,10A1.5,1.5 0 0,0 14,11.5A1.5,1.5 0 0,0 15.5,10A1.5,1.5 0 0,0 14,8.5M14,12.5A1.5,1.5 0 0,0 12.5,14A1.5,1.5 0 0,0 14,15.5A1.5,1.5 0 0,0 15.5,14A1.5,1.5 0 0,0 14,12.5M10,17A1,1 0 0,0 9,18A1,1 0 0,0 10,19A1,1 0 0,0 11,18A1,1 0 0,0 10,17M10,8.5A1.5,1.5 0 0,0 8.5,10A1.5,1.5 0 0,0 10,11.5A1.5,1.5 0 0,0 11.5,10A1.5,1.5 0 0,0 10,8.5M14,20.5A0.5,0.5 0 0,0 13.5,21A0.5,0.5 0 0,0 14,21.5A0.5,0.5 0 0,0 14.5,21A0.5,0.5 0 0,0 14,20.5M14,17A1,1 0 0,0 13,18A1,1 0 0,0 14,19A1,1 0 0,0 15,18A1,1 0 0,0 14,17M21,13.5A0.5,0.5 0 0,0 20.5,14A0.5,0.5 0 0,0 21,14.5A0.5,0.5 0 0,0 21.5,14A0.5,0.5 0 0,0 21,13.5M18,5A1,1 0 0,0 17,6A1,1 0 0,0 18,7A1,1 0 0,0 19,6A1,1 0 0,0 18,5M18,9A1,1 0 0,0 17,10A1,1 0 0,0 18,11A1,1 0 0,0 19,10A1,1 0 0,0 18,9M18,17A1,1 0 0,0 17,18A1,1 0 0,0 18,19A1,1 0 0,0 19,18A1,1 0 0,0 18,17M18,13A1,1 0 0,0 17,14A1,1 0 0,0 18,15A1,1 0 0,0 19,14A1,1 0 0,0 18,13M10,12.5A1.5,1.5 0 0,0 8.5,14A1.5,1.5 0 0,0 10,15.5A1.5,1.5 0 0,0 11.5,14A1.5,1.5 0 0,0 10,12.5M10,7A1,1 0 0,0 11,6A1,1 0 0,0 10,5A1,1 0 0,0 9,6A1,1 0 0,0 10,7M10,3.5A0.5,0.5 0 0,0 10.5,3A0.5,0.5 0 0,0 10,2.5A0.5,0.5 0 0,0 9.5,3A0.5,0.5 0 0,0 10,3.5M10,20.5A0.5,0.5 0 0,0 9.5,21A0.5,0.5 0 0,0 10,21.5A0.5,0.5 0 0,0 10.5,21A0.5,0.5 0 0,0 10,20.5M3,13.5A0.5,0.5 0 0,0 2.5,14A0.5,0.5 0 0,0 3,14.5A0.5,0.5 0 0,0 3.5,14A0.5,0.5 0 0,0 3,13.5M14,3.5A0.5,0.5 0 0,0 14.5,3A0.5,0.5 0 0,0 14,2.5A0.5,0.5 0 0,0 13.5,3A0.5,0.5 0 0,0 14,3.5M14,7A1,1 0 0,0 15,6A1,1 0 0,0 14,5A1,1 0 0,0 13,6A1,1 0 0,0 14,7M21,10.5A0.5,0.5 0 0,0 21.5,10A0.5,0.5 0 0,0 21,9.5A0.5,0.5 0 0,0 20.5,10A0.5,0.5 0 0,0 21,10.5M6,5A1,1 0 0,0 5,6A1,1 0 0,0 6,7A1,1 0 0,0 7,6A1,1 0 0,0 6,5M3,9.5A0.5,0.5 0 0,0 2.5,10A0.5,0.5 0 0,0 3,10.5A0.5,0.5 0 0,0 3.5,10A0.5,0.5 0 0,0 3,9.5M6,9A1,1 0 0,0 5,10A1,1 0 0,0 6,11A1,1 0 0,0 7,10A1,1 0 0,0 6,9M6,17A1,1 0 0,0 5,18A1,1 0 0,0 6,19A1,1 0 0,0 7,18A1,1 0 0,0 6,17M6,13A1,1 0 0,0 5,14A1,1 0 0,0 6,15A1,1 0 0,0 7,14A1,1 0 0,0 6,13Z" />
</vector>

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M23.5,17L18.5,22L15,18.5L16.5,17L18.5,19L22,15.5L23.5,17M12,9A3,3 0 0,1 15,12A3,3 0 0,1 12,15A3,3 0 0,1 9,12A3,3 0 0,1 12,9M12,4.5C17,4.5 21.27,7.61 23,12C22.75,12.65 22.44,13.26 22.08,13.85C21.5,13.5 20.86,13.25 20.18,13.12L20.82,12C19.17,8.64 15.76,6.5 12,6.5C8.24,6.5 4.83,8.64 3.18,12C4.83,15.36 8.24,17.5 12,17.5L13.21,17.43C13.07,17.93 13,18.46 13,19V19.46L12,19.5C7,19.5 2.73,16.39 1,12C2.73,7.61 7,4.5 12,4.5Z" />
</vector>

View file

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#000"
android:pathData="M11,4V1H13V4ZM11,23V20H13V23ZM20,13V11H23V13ZM1,13V11H4V13ZM18.7,6.7 L17.3,5.3 19.05,3.5 20.5,4.95ZM4.95,20.5 L3.5,19.05 5.3,17.3 6.7,18.7ZM19.05,20.5 L17.3,18.7 18.7,17.3 20.5,19.05ZM5.3,6.7 L3.5,4.95 4.95,3.5 6.7,5.3ZM12,18Q9.5,18 7.75,16.25Q6,14.5 6,12Q6,9.5 7.75,7.75Q9.5,6 12,6Q14.5,6 16.25,7.75Q18,9.5 18,12Q18,14.5 16.25,16.25Q14.5,18 12,18ZM12,16Q13.675,16 14.838,14.837Q16,13.675 16,12Q16,10.325 14.838,9.162Q13.675,8 12,8Q10.325,8 9.163,9.162Q8,10.325 8,12Q8,13.675 9.163,14.837Q10.325,16 12,16ZM12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Q12,12 12,12Z"/>
</vector>

View file

@ -0,0 +1,11 @@
<!-- drawable/ic_info_outline.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#000"
android:pathData="M11,17h2v-6h-2v6zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,9h2L13,7h-2v2z" />
</vector>

View file

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2017-2021 crDroid Android 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="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:gravity="center_vertical"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/activatedBackgroundIndicator"
android:clipToPadding="false">
<include layout="@layout/settingslib_icon_frame"/>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceListItem"
android:ellipsize="marquee" />
<TextView
android:id="@android:id/summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/title"
android:layout_alignStart="@android:id/title"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="10"
android:ellipsize="end" />
<RelativeLayout
android:id="@+id/value_frame"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@android:id/summary"
android:layout_alignStart="@android:id/title" >
<TextView
android:id="@+id/value"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:textAppearance="?android:attr/textAppearanceListItemSecondary"
android:textColor="?android:attr/textColorSecondary"
android:maxLines="1"
android:ellipsize="end" />
<ImageView
android:id="@+id/reset"
android:src="@drawable/ic_custom_seekbar_reset"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:layout_toEndOf="@id/value"
android:layout_centerVertical="true" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/seekbar_frame"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/value_frame"
android:layout_alignStart="@android:id/title" >
<ImageView
android:id="@+id/minus"
android:src="@drawable/ic_custom_seekbar_minus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true" />
<ImageView
android:id="@+id/plus"
android:src="@drawable/ic_custom_seekbar_plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true" />
<LinearLayout
android:id="@+id/seekbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_toEndOf="@id/minus"
android:layout_toStartOf="@id/plus"
android:layout_centerVertical="true" />
</RelativeLayout>
</RelativeLayout>
<!-- Preference should place its actual preference widget here. -->
<LinearLayout android:id="@android:id/widget_frame"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="end|center_vertical"
android:paddingStart="16dp"
android:orientation="vertical" />
</LinearLayout>

View file

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016-2021 crDroid Android 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.
-->
<resources>
<!-- Base attributes available to CustomSeekBarPreference. -->
<declare-styleable name="CustomSeekBarPreference">
<attr name="defaultValueText" format="string" />
<attr name="interval" format="integer" />
<attr name="showSign" format="boolean" />
<attr name="units" format="string|reference" />
<attr name="continuousUpdates" format="boolean" />
</declare-styleable>
</resources>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="custom_seekbar_value">Value: <xliff:g id="v">%s</xliff:g></string>
<string name="custom_seekbar_default_value">by default</string>
<string name="custom_seekbar_default_value_to_set">Default value: <xliff:g id="v">%s</xliff:g>\nLong tap to set</string>
<string name="custom_seekbar_default_value_is_set">Default value is set</string>
</resources>

View file

@ -47,5 +47,23 @@
<string name="clear_speaker_title">Clear speaker</string> <string name="clear_speaker_title">Clear speaker</string>
<string name="clear_speaker_summary">Play a 30-second audio to clear the speaker</string> <string name="clear_speaker_summary">Play a 30-second audio to clear the speaker</string>
<string name="clear_speaker_description">Run this feature once or twice if you find that your speaker is lightly blocked by dust. Set media volume to maximum.\n\nIf the speaker is blocked heavily, run this feature 2-5 times while shaking your device with the speaker facing downwards.</string> <string name="clear_speaker_description">Run this feature once or twice if you find that your speaker is lightly blocked by dust. Set media volume to maximum.\n\nIf the speaker is blocked heavily, run this feature 2-5 times while shaking your device with the speaker facing downwards.</string>
<!-- HBM settings -->
<string name="hbm_fragment_title">High brightness mode</string>
<string name="hbm_fragment_summary">Settings for HBM</string>
<string name="hbm_mode_title">HBM</string>
<string name="hbm_mode_summary">Enable peak luminance</string>
<string name="auto_hbm_title">Automatic HBM</string>
<string name="auto_hbm_summary">Enable peak luminance based on sunlight</string>
<string name="auto_hbm_threshold_title"></string>
<string name="auto_hbm_threshold_summary">threshold (lux)</string>
<string name="hbm_disable_time_title"></string>
<string name="hbm_disable_time_summary">disable delay (seconds)</string>
<string name="hbm_mode_warning">Long time usage of High brightness mode may damage your display</string>
<!-- DC dimming settings -->
<string name="dc_dimming_enable_title">DC Dimming</string>
<string name="dc_dimming_enable_summary">Reduces eye strain in low light conditions</string>
<string name="dc_dimming_enable_summary_not_supported">DC Dimming is currently not supported by the kernel</string>
</resources> </resources>

View file

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The CyanogenMod Project
2018-2019 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License"
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/dc_dimming_enable_title">
<SwitchPreference
android:key="dc_dimming_enable"
android:defaultValue="false"
android:icon="@drawable/ic_dcdimming"
android:title="@string/dc_dimming_enable_title"
android:summary="@string/dc_dimming_enable_summary" />
</PreferenceScreen>

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2021 The Evolution X Project
Copyright (C) 2018-2021 crDroid Android 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"
xmlns:settings="http://schemas.android.com/apk/res/org.lineageos.settings.HBMFragment"
android.title="@string/hbm_fragment_title">
<PreferenceCategory>
<SwitchPreference
android:key="hbm"
android:title="@string/hbm_mode_title"
android:summary="@string/hbm_mode_summary"
android:defaultValue="false" />
<SwitchPreference
android:key="auto_hbm"
android:title="@string/auto_hbm_title"
android:summary="@string/auto_hbm_summary" />
<org.lineageos.settings.hbm.AutoHBMThresholdPreference
android:key="auto_hbm_threshold"
android:title="@string/auto_hbm_threshold_title"
android:summary="@string/auto_hbm_threshold_summary" />
<org.lineageos.settings.hbm.AutoHBMTimePreference
android:key="hbm_disable_time"
android:title="@string/hbm_disable_time_title"
android:summary="@string/hbm_disable_time_summary" />
<Preference
android:icon="@drawable/ic_info_outline"
android:summary="@string/hbm_mode_warning"
android:persistent="false" />
</PreferenceCategory>
</PreferenceScreen>

View file

@ -21,21 +21,33 @@ import android.content.BroadcastReceiver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.util.Log; import android.util.Log;
import android.content.SharedPreferences;
import android.os.SystemProperties;
import androidx.preference.PreferenceManager;
import org.lineageos.settings.doze.DozeUtils; import org.lineageos.settings.doze.DozeUtils;
import org.lineageos.settings.thermal.ThermalUtils; import org.lineageos.settings.thermal.ThermalUtils;
import org.lineageos.settings.refreshrate.RefreshUtils; import org.lineageos.settings.refreshrate.RefreshUtils;
import org.lineageos.settings.utils.FileUtils;
public class BootCompletedReceiver extends BroadcastReceiver { public class BootCompletedReceiver extends BroadcastReceiver {
private static final boolean DEBUG = false; private static final boolean DEBUG = false;
private static final String TAG = "XiaomiParts"; private static final String TAG = "XiaomiParts";
private static final String DC_DIMMING_ENABLE_KEY = "dc_dimming_enable";
private static final String DC_DIMMING_NODE = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/dimlayer_exposure";
@Override @Override
public void onReceive(final Context context, Intent intent) { public void onReceive(final Context context, Intent intent) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
if (DEBUG) if (DEBUG)
Log.d(TAG, "Received boot completed intent"); Log.d(TAG, "Received boot completed intent");
DozeUtils.onBootCompleted(context); DozeUtils.onBootCompleted(context);
ThermalUtils.startService(context); ThermalUtils.startService(context);
RefreshUtils.startService(context); RefreshUtils.startService(context);
// DC Dimming
FileUtils.enableService(context);
boolean dcDimmingEnabled = sharedPrefs.getBoolean(DC_DIMMING_ENABLE_KEY, false);
FileUtils.writeLine(DC_DIMMING_NODE, dcDimmingEnabled ? "1" : "0");
} }
} }

View file

@ -0,0 +1,34 @@
/*
* Copyright (C) 2015-2016 The CyanogenMod Project
* 2017,2021-2022 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.display;
import android.os.Bundle;
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
public class DcDimmingSettingsActivity extends CollapsingToolbarBaseActivity {
private static final String TAG_DCDIMMING = "dcdimming";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getFragmentManager().beginTransaction().replace(com.android.settingslib.collapsingtoolbar.R.id.content_frame,
new DcDimmingSettingsFragment(), TAG_DCDIMMING).commit();
}
}

View file

@ -0,0 +1,102 @@
/*
* Copyright (C) 2018 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.display;
import android.content.Context;
import android.os.Bundle;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import androidx.preference.SwitchPreference;
import android.provider.Settings;
import org.lineageos.settings.R;
import org.lineageos.settings.utils.FileUtils;
import java.io.File;
public class DcDimmingSettingsFragment extends PreferenceFragment implements
OnPreferenceChangeListener {
private SwitchPreference mDcDimmingPreference;
private static final String DC_DIMMING_ENABLE_KEY = "dc_dimming_enable";
private static final String DC_DIMMING_NODE = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/dimlayer_exposure";
private static final String HBM = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/hbm";
private static final String HBM_KEY = "hbm";
private File hbmFile;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
setPreferencesFromResource(R.xml.dcdimming_settings, rootKey);
mDcDimmingPreference = findPreference(DC_DIMMING_ENABLE_KEY);
if (FileUtils.fileExists(DC_DIMMING_NODE)) {
mDcDimmingPreference.setEnabled(true);
mDcDimmingPreference.setOnPreferenceChangeListener(this);
} else {
mDcDimmingPreference.setSummary(R.string.dc_dimming_enable_summary_not_supported);
mDcDimmingPreference.setEnabled(false);
}
hbmFile = new File(HBM);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (DC_DIMMING_ENABLE_KEY.equals(preference.getKey())) {
boolean enabled = (boolean) newValue;
FileUtils.writeLine(DC_DIMMING_NODE, enabled ? "1" : "0");
if (enabled) {
disableHBM();
}
updateHBMPreference(!enabled);
}
return true;
}
private void disableHBM() {
// Disable HBM mode
FileUtils.writeLine(HBM, "0");
// Make HBM mode path read-only
hbmFile.setReadOnly();
// Update HBM mode UI tile
updateHBMUI(false);
}
private void updateHBMUI(boolean enabled) {
Intent intent = new Intent("org.lineageos.settings.hbm.UPDATE_TILE");
intent.putExtra("enabled", enabled);
getActivity().sendBroadcast(intent);
// Update HBM preference UI
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
sharedPrefs.edit().putBoolean(HBM_KEY, enabled).apply();
updateHBMPreference(enabled);
}
private void updateHBMPreference(boolean enabled) {
// Update HBM preference UI
if (mDcDimmingPreference != null) {
mDcDimmingPreference.setChecked(enabled);
}
}
}

View file

@ -0,0 +1,125 @@
/*
* Copyright (C) 2018 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.lineageos.settings.display;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.BroadcastReceiver;
import android.content.IntentFilter;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import androidx.preference.PreferenceManager;
import android.provider.Settings;
import org.lineageos.settings.utils.FileUtils;
import java.io.File;
public class DcDimmingTileService extends TileService {
public static final String DC_DIMMING_ENABLE_KEY = "dc_dimming_enable";
private static final String DC_DIMMING_NODE = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/dimlayer_exposure";
private static final String HBM = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/hbm";
private static final String HBM_KEY = "hbm";
private File hbmFile;
private BroadcastReceiver screenStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
Editor editor = sharedPrefs.edit();
editor.putBoolean(DC_DIMMING_ENABLE_KEY, false);
editor.apply();
updateUI(false);
disableHBM();
}
}
};
private void updateUI(boolean enabled) {
final Tile tile = getQsTile();
tile.setState(enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.updateTile();
}
private void disableHBM() {
// Disable HBM mode
FileUtils.writeLine(HBM, "0");
// Make HBM mode path read-only
hbmFile.setReadOnly();
// Update HBM mode UI tile
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
Editor editor = sharedPrefs.edit();
editor.putBoolean(HBM_KEY, false);
editor.apply();
updateHBMUI(false);
}
private void updateHBMUI(boolean enabled) {
Intent intent = new Intent("org.lineageos.settings.hbm.UPDATE_TILE");
intent.putExtra("enabled", enabled);
sendBroadcast(intent);
}
@Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenStateReceiver, filter);
hbmFile = new File(HBM);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(screenStateReceiver);
}
@Override
public void onStartListening() {
super.onStartListening();
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
updateUI(sharedPrefs.getBoolean(DC_DIMMING_ENABLE_KEY, false));
}
@Override
public void onStopListening() {
super.onStopListening();
}
@Override
public void onClick() {
super.onClick();
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
final boolean enabled = !(sharedPrefs.getBoolean(DC_DIMMING_ENABLE_KEY, false));
FileUtils.writeLine(DC_DIMMING_NODE, enabled ? "1" : "0");
if (enabled) {
disableHBM();
} else {
hbmFile.setWritable(true);
}
sharedPrefs.edit().putBoolean(DC_DIMMING_ENABLE_KEY, enabled).apply();
updateUI(enabled);
}
}

View file

@ -0,0 +1,155 @@
package org.lineageos.settings.hbm;
import android.app.KeyguardManager;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.IBinder;
import android.os.PowerManager;
import androidx.preference.PreferenceManager;
import android.provider.Settings;
import org.lineageos.settings.utils.FileUtils;
import org.lineageos.settings.display.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class AutoHBMService extends Service {
private static final String HBM = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/hbm_enabled";
private static final String BACKLIGHT = "/sys/class/backlight/panel0-backlight/brightness";
private static boolean mAutoHBMActive = false;
private ExecutorService mExecutorService;
private SensorManager mSensorManager;
Sensor mLightSensor;
private SharedPreferences mSharedPrefs;
private boolean dcDimmingEnabled;
public void activateLightSensorRead() {
submit(() -> {
mSensorManager = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
mSensorManager.registerListener(mSensorEventListener, mLightSensor, SensorManager.SENSOR_DELAY_NORMAL);
});
}
public void deactivateLightSensorRead() {
submit(() -> {
mSensorManager.unregisterListener(mSensorEventListener);
mAutoHBMActive = false;
enableHBM(false);
});
}
private void enableHBM(boolean enable) {
if (enable) {
FileUtils.writeLine(HBM, "1");
FileUtils.writeLine(BACKLIGHT, "2047");
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 255);
} else {
FileUtils.writeLine(HBM, "0");
}
}
private boolean isCurrentlyEnabled() {
return FileUtils.getFileValueAsBoolean(HBM, false);
}
private SensorEventListener mSensorEventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
float lux = event.values[0];
KeyguardManager km =
(KeyguardManager) getSystemService(getApplicationContext().KEYGUARD_SERVICE);
boolean keyguardShowing = km.inKeyguardRestrictedInputMode();
float luxThreshold = Float.parseFloat(mSharedPrefs.getString(HBMFragment.KEY_AUTO_HBM_THRESHOLD, "20000"));
long timeToDisableHBM = Long.parseLong(mSharedPrefs.getString(HBMFragment.KEY_HBM_DISABLE_TIME, "1"));
if (lux > luxThreshold) {
if ((!mAutoHBMActive || !isCurrentlyEnabled()) && !keyguardShowing && !dcDimmingEnabled) {
mAutoHBMActive = true;
enableHBM(true);
}
}
if (lux < luxThreshold) {
if (mAutoHBMActive) {
mExecutorService.submit(() -> {
try {
Thread.sleep(timeToDisableHBM * 1000);
} catch (InterruptedException e) {
}
if (lux < luxThreshold) {
mAutoHBMActive = false;
enableHBM(false);
}
});
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// do nothing
}
};
private BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
activateLightSensorRead();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
deactivateLightSensorRead();
}
}
};
@Override
public void onCreate() {
mExecutorService = Executors.newSingleThreadExecutor();
IntentFilter screenStateFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenStateReceiver, screenStateFilter);
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm.isInteractive()) {
activateLightSensorRead();
}
}
private Future < ? > submit(Runnable runnable) {
return mExecutorService.submit(runnable);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(mScreenStateReceiver);
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
if (pm.isInteractive()) {
deactivateLightSensorRead();
}
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2016 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.lineageos.settings.hbm;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.AttributeSet;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceViewHolder;
public class AutoHBMThresholdPreference extends CustomSeekBarPreference {
private static int mMinVal = 0;
private static int mMaxVal = 60000;
private static int mDefVal = 20000;
public AutoHBMThresholdPreference(Context context, AttributeSet attrs) {
super(context, attrs);
mInterval = 1000;
mShowSign = false;
mUnits = "";
mContinuousUpdates = false;
mMinValue = mMinVal;
mMaxValue = mMaxVal;
mDefaultValueExists = true;
mDefaultValue = mDefVal;
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
mValue = Integer.parseInt(sharedPrefs.getString(HBMFragment.KEY_AUTO_HBM_THRESHOLD, "20000"));
setPersistent(false);
}
@Override
protected void changeValue(int newValue) {
SharedPreferences.Editor prefChange = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
prefChange.putString(HBMFragment.KEY_AUTO_HBM_THRESHOLD, String.valueOf(newValue)).commit();
}
}

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2016 The OmniROM Project
2023 The Evolution X Project
* SPDX-License-Identifier: GPL-2.0-or-later
*/
package org.lineageos.settings.hbm;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.Log;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceViewHolder;
public class AutoHBMTimePreference extends CustomSeekBarPreference {
private static int mMinVal = 1;
private static int mMaxVal = 10;
private static int mDefVal = 1;
public AutoHBMTimePreference(Context context, AttributeSet attrs) {
super(context, attrs);
mInterval = 1;
mShowSign = false;
mUnits = "";
mContinuousUpdates = false;
mMinValue = mMinVal;
mMaxValue = mMaxVal;
mDefaultValueExists = true;
mDefaultValue = mDefVal;
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
mValue = Integer.parseInt(sharedPrefs.getString(HBMFragment.KEY_HBM_DISABLE_TIME, "1"));
setPersistent(false);
}
@Override
protected void changeValue(int newValue) {
SharedPreferences.Editor prefChange = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
prefChange.putString(HBMFragment.KEY_HBM_DISABLE_TIME, String.valueOf(newValue)).commit();
}
}

View file

@ -0,0 +1,367 @@
/*
* Copyright (C) 2016-2021 crDroid Android 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.lineageos.settings.hbm;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.PorterDuff;
import androidx.core.content.res.TypedArrayUtils;
import androidx.preference.*;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;
import org.lineageos.settings.R;
public class CustomSeekBarPreference extends Preference implements SeekBar.OnSeekBarChangeListener {
protected final String TAG = getClass().getName();
private static final String SETTINGS_NS = "http://schemas.android.com/apk/res/com.android.settings";
protected static final String ANDROIDNS = "http://schemas.android.com/apk/res/android";
protected int mInterval = 1;
protected boolean mShowSign = false;
protected String mUnits = "";
protected boolean mContinuousUpdates = false;
protected int mMinValue = 0;
protected int mMaxValue = 100;
protected boolean mDefaultValueExists = false;
protected int mDefaultValue;
protected boolean mDefaultValueTextExists = false;
protected String mDefaultValueText;
protected int mValue;
protected TextView mValueTextView;
protected ImageView mResetImageView;
protected ImageView mMinusImageView;
protected ImageView mPlusImageView;
protected SeekBar mSeekBar;
protected boolean mTrackingTouch = false;
protected int mTrackingValue;
public CustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomSeekBarPreference);
try {
mShowSign = a.getBoolean(R.styleable.CustomSeekBarPreference_showSign, mShowSign);
String units = a.getString(R.styleable.CustomSeekBarPreference_units);
if (units != null)
mUnits = " " + units;
mContinuousUpdates = a.getBoolean(R.styleable.CustomSeekBarPreference_continuousUpdates, mContinuousUpdates);
String defaultValueText = a.getString(R.styleable.CustomSeekBarPreference_defaultValueText);
mDefaultValueTextExists = defaultValueText != null && !defaultValueText.isEmpty();
if (mDefaultValueTextExists) {
mDefaultValueText = defaultValueText;
}
} finally {
a.recycle();
}
try {
String newInterval = attrs.getAttributeValue(SETTINGS_NS, "interval");
if (newInterval != null)
mInterval = Integer.parseInt(newInterval);
} catch (Exception e) {
Log.e(TAG, "Invalid interval value", e);
}
mMinValue = attrs.getAttributeIntValue(SETTINGS_NS, "min", mMinValue);
mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", mMaxValue);
if (mMaxValue < mMinValue)
mMaxValue = mMinValue;
String defaultValue = attrs.getAttributeValue(ANDROIDNS, "defaultValue");
mDefaultValueExists = defaultValue != null && !defaultValue.isEmpty();
if (mDefaultValueExists) {
mDefaultValue = getLimitedValue(Integer.parseInt(defaultValue));
mValue = mDefaultValue;
} else {
mValue = mMinValue;
}
mSeekBar = new SeekBar(context, attrs);
setLayoutResource(R.layout.preference_custom_seekbar);
}
public CustomSeekBarPreference(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public CustomSeekBarPreference(Context context, AttributeSet attrs) {
this(context, attrs, TypedArrayUtils.getAttr(context,
androidx.preference.R.attr.preferenceStyle,
android.R.attr.preferenceStyle));
}
public CustomSeekBarPreference(Context context) {
this(context, null);
}
@Override
public void onDependencyChanged(Preference dependency, boolean disableDependent) {
super.onDependencyChanged(dependency, disableDependent);
this.setShouldDisableView(true);
if (mSeekBar != null)
mSeekBar.setEnabled(!disableDependent);
if (mResetImageView != null)
mResetImageView.setEnabled(!disableDependent);
if (mPlusImageView != null)
mPlusImageView.setEnabled(!disableDependent);
if (mMinusImageView != null)
mMinusImageView.setEnabled(!disableDependent);
}
@Override
public void onBindViewHolder(PreferenceViewHolder holder) {
super.onBindViewHolder(holder);
try
{
// move our seekbar to the new view we've been given
ViewParent oldContainer = mSeekBar.getParent();
ViewGroup newContainer = (ViewGroup) holder.findViewById(R.id.seekbar);
if (oldContainer != newContainer) {
// remove the seekbar from the old view
if (oldContainer != null) {
((ViewGroup) oldContainer).removeView(mSeekBar);
}
// remove the existing seekbar (there may not be one) and add ours
newContainer.removeAllViews();
newContainer.addView(mSeekBar, ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
} catch (Exception ex) {
Log.e(TAG, "Error binding view: " + ex.toString());
}
mSeekBar.setMax(getSeekValue(mMaxValue));
mSeekBar.setProgress(getSeekValue(mValue));
mSeekBar.setEnabled(isEnabled());
mValueTextView = (TextView) holder.findViewById(R.id.value);
mResetImageView = (ImageView) holder.findViewById(R.id.reset);
mMinusImageView = (ImageView) holder.findViewById(R.id.minus);
mPlusImageView = (ImageView) holder.findViewById(R.id.plus);
updateValueViews();
mSeekBar.setOnSeekBarChangeListener(this);
mResetImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(), getContext().getString(R.string.custom_seekbar_default_value_to_set, getTextValue(mDefaultValue)),
Toast.LENGTH_LONG).show();
}
});
mResetImageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
setValue(mDefaultValue, true);
return true;
}
});
mMinusImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setValue(mValue - mInterval, true);
}
});
mMinusImageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
setValue(mMaxValue - mMinValue > mInterval * 2 && mMaxValue + mMinValue < mValue * 2 ? Math.floorDiv(mMaxValue + mMinValue, 2) : mMinValue, true);
return true;
}
});
mPlusImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
setValue(mValue + mInterval, true);
}
});
mPlusImageView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
setValue(mMaxValue - mMinValue > mInterval * 2 && mMaxValue + mMinValue > mValue * 2 ? -1 * Math.floorDiv(-1 * (mMaxValue + mMinValue), 2) : mMaxValue, true);
return true;
}
});
}
protected int getLimitedValue(int v) {
return v < mMinValue ? mMinValue : (v > mMaxValue ? mMaxValue : v);
}
protected int getSeekValue(int v) {
return 0 - Math.floorDiv(mMinValue - v, mInterval);
}
protected String getTextValue(int v) {
if (mDefaultValueTextExists && mDefaultValueExists && v == mDefaultValue) {
return mDefaultValueText;
}
return (mShowSign && v > 0 ? "+" : "") + String.valueOf(v) + mUnits;
}
protected void updateValueViews() {
if (mValueTextView != null) {
if (!mTrackingTouch || mContinuousUpdates) {
if (mDefaultValueTextExists && mDefaultValueExists && mValue == mDefaultValue) {
mValueTextView.setText(mDefaultValueText + " (" +
getContext().getString(R.string.custom_seekbar_default_value) + ")");
} else {
mValueTextView.setText(getContext().getString(R.string.custom_seekbar_value, getTextValue(mValue)) +
(mDefaultValueExists && mValue == mDefaultValue ? " (" +
getContext().getString(R.string.custom_seekbar_default_value) + ")" : ""));
}
} else {
if (mDefaultValueTextExists && mDefaultValueExists && mTrackingValue == mDefaultValue) {
mValueTextView.setText("[" + mDefaultValueText + "]");
} else {
mValueTextView.setText(getContext().getString(R.string.custom_seekbar_value, "[" + getTextValue(mTrackingValue) + "]"));
}
}
}
if (mResetImageView != null) {
if (!mDefaultValueExists || mValue == mDefaultValue || mTrackingTouch)
mResetImageView.setVisibility(View.INVISIBLE);
else
mResetImageView.setVisibility(View.VISIBLE);
}
if (mMinusImageView != null) {
if (mValue == mMinValue || mTrackingTouch) {
mMinusImageView.setClickable(false);
mMinusImageView.setColorFilter(getContext().getColor(R.color.disabled_text_color),
PorterDuff.Mode.MULTIPLY);
} else {
mMinusImageView.setClickable(true);
mMinusImageView.clearColorFilter();
}
}
if (mPlusImageView != null) {
if (mValue == mMaxValue || mTrackingTouch) {
mPlusImageView.setClickable(false);
mPlusImageView.setColorFilter(getContext().getColor(R.color.disabled_text_color), PorterDuff.Mode.MULTIPLY);
} else {
mPlusImageView.setClickable(true);
mPlusImageView.clearColorFilter();
}
}
}
protected void changeValue(int newValue) {
// for subclasses
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
int newValue = getLimitedValue(mMinValue + (progress * mInterval));
if (mTrackingTouch && !mContinuousUpdates) {
mTrackingValue = newValue;
updateValueViews();
} else if (mValue != newValue) {
// change rejected, revert to the previous value
if (!callChangeListener(newValue)) {
mSeekBar.setProgress(getSeekValue(mValue));
return;
}
// change accepted, store it
changeValue(newValue);
persistInt(newValue);
mValue = newValue;
updateValueViews();
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mTrackingValue = mValue;
mTrackingTouch = true;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
mTrackingTouch = false;
if (!mContinuousUpdates)
onProgressChanged(mSeekBar, getSeekValue(mTrackingValue), false);
notifyChanged();
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
if (restoreValue)
mValue = getPersistedInt(mValue);
}
@Override
public void setDefaultValue(Object defaultValue) {
if (defaultValue instanceof Integer)
setDefaultValue((Integer) defaultValue, mSeekBar != null);
else
setDefaultValue(defaultValue == null ? (String) null : defaultValue.toString(), mSeekBar != null);
}
public void setDefaultValue(int newValue, boolean update) {
newValue = getLimitedValue(newValue);
if (!mDefaultValueExists || mDefaultValue != newValue) {
mDefaultValueExists = true;
mDefaultValue = newValue;
if (update)
updateValueViews();
}
}
public void setDefaultValue(String newValue, boolean update) {
if (mDefaultValueExists && (newValue == null || newValue.isEmpty())) {
mDefaultValueExists = false;
if (update)
updateValueViews();
} else if (newValue != null && !newValue.isEmpty()) {
setDefaultValue(Integer.parseInt(newValue), update);
}
}
public void setValue(int newValue) {
mValue = getLimitedValue(newValue);
if (mSeekBar != null) mSeekBar.setProgress(getSeekValue(mValue));
}
public void setValue(int newValue, boolean update) {
newValue = getLimitedValue(newValue);
if (mValue != newValue) {
if (update)
mSeekBar.setProgress(getSeekValue(newValue));
else
mValue = newValue;
}
}
public int getValue() {
return mValue;
}
public void refresh(int newValue) {
// this will ...
setValue(newValue, mSeekBar != null);
}
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (C) 2017 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.lineageos.settings.hbm;
import android.app.Fragment;
import android.os.Bundle;
import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceManager;
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
public class HBMActivity extends CollapsingToolbarBaseActivity {
private HBMFragment mHBMFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Fragment fragment = getFragmentManager().findFragmentById(com.android.settingslib.collapsingtoolbar.R.id.content_frame);
if (fragment == null) {
mHBMFragment = new HBMFragment();
getFragmentManager().beginTransaction()
.add(com.android.settingslib.collapsingtoolbar.R.id.content_frame, mHBMFragment)
.commit();
} else {
mHBMFragment = (HBMFragment) fragment;
}
}
}

View file

@ -0,0 +1,80 @@
/*
* Copyright (C) 2016 The OmniROM Project
* Copyright (C) 2018-2021 crDroid Android Project
* Copyright (C) 2019-2022 Evolution X 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.lineageos.settings.hbm;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.util.Log;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragment;
import androidx.preference.PreferenceManager;
import androidx.preference.TwoStatePreference;
import org.lineageos.settings.utils.FileUtils;
import org.lineageos.settings.R;
public class HBMFragment extends PreferenceFragment
implements Preference.OnPreferenceChangeListener {
private static final String TAG = HBMFragment.class.getSimpleName();
public static final String KEY_HBM_SWITCH = "hbm";
public static final String KEY_AUTO_HBM_SWITCH = "auto_hbm";
public static final String KEY_AUTO_HBM_THRESHOLD = "auto_hbm_threshold";
public static final String KEY_HBM_DISABLE_TIME = "hbm_disable_time";
private static TwoStatePreference mHBMModeSwitch;
private static TwoStatePreference mAutoHBMSwitch;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this.getContext());
addPreferencesFromResource(R.xml.hbm_settings);
// HBM
mHBMModeSwitch = (TwoStatePreference) findPreference(KEY_HBM_SWITCH);
mHBMModeSwitch.setOnPreferenceChangeListener(new HBMModeSwitch(getContext()));
// AutoHBM
mAutoHBMSwitch = (TwoStatePreference) findPreference(KEY_AUTO_HBM_SWITCH);
mAutoHBMSwitch.setOnPreferenceChangeListener(this);
mAutoHBMSwitch.setChecked(PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean(HBMFragment.KEY_AUTO_HBM_SWITCH, false));
}
public static boolean isAUTOHBMEnabled(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(HBMFragment.KEY_AUTO_HBM_SWITCH, false);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mAutoHBMSwitch) {
Boolean enabled = (Boolean) newValue;
SharedPreferences.Editor prefChange = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
prefChange.putBoolean(KEY_AUTO_HBM_SWITCH, enabled).commit();
FileUtils.enableService(getContext());
return true;
}
return false;
}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2016 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.lineageos.settings.hbm;
import android.provider.Settings;
import android.content.Context;
import android.content.SharedPreferences;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceManager;
import org.lineageos.settings.utils.FileUtils;
import org.lineageos.settings.display.*;
public class HBMModeSwitch implements OnPreferenceChangeListener {
private static final String HBM = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/hbm_enabled";
private static final String BACKLIGHT = "/sys/class/backlight/panel0-backlight/brightness";
private Context mContext;
public HBMModeSwitch(Context context) {
mContext = context;
}
public static String getHBM() {
if (FileUtils.isFileWritable(HBM)) {
return HBM;
}
return null;
}
public static String getBACKLIGHT() {
if (FileUtils.isFileWritable(BACKLIGHT)) {
return BACKLIGHT;
}
return null;
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Boolean enabled = (Boolean) newValue;
boolean dcDimmingEnabled = PreferenceManager.getDefaultSharedPreferences(mContext).getBoolean(DcDimmingTileService.DC_DIMMING_ENABLE_KEY, false);
if (dcDimmingEnabled) {
return false;
}
FileUtils.writeLine(getHBM(), enabled ? "1" : "0");
if (enabled) {
FileUtils.writeLine(getBACKLIGHT(), "2047");
Settings.System.putInt(mContext.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 255);
}
return true;
}
}

View file

@ -0,0 +1,100 @@
/*
* Copyright (C) 2018 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.lineageos.settings.hbm;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.BroadcastReceiver;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
import androidx.preference.PreferenceManager;
import android.provider.Settings;
import org.lineageos.settings.utils.FileUtils;
import org.lineageos.settings.display.*;
public class HBMModeTileService extends TileService {
private static final String HBM = "/sys/devices/platform/soc/soc:qcom,dsi-display-primary/hbm_enabled";
private static final String HBM_KEY = "hbm";
private static final String BACKLIGHT = "/sys/class/backlight/panel0-backlight/brightness";
private BroadcastReceiver screenStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
sharedPrefs.edit().putBoolean(HBM_KEY, false).commit();
updateUI(false);
}
}
};
private void updateUI(boolean enabled) {
final Tile tile = getQsTile();
tile.setState(enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
tile.updateTile();
}
@Override
public void onCreate() {
super.onCreate();
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(screenStateReceiver, filter);
}
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(screenStateReceiver);
}
@Override
public void onStartListening() {
super.onStartListening();
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
updateUI(sharedPrefs.getBoolean(HBM_KEY, false));
}
@Override
public void onStopListening() {
super.onStopListening();
}
@Override
public void onClick() {
super.onClick();
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
final boolean dcDimmingEnabled = sharedPrefs.getBoolean(DcDimmingTileService.DC_DIMMING_ENABLE_KEY, false);
if (dcDimmingEnabled) {
return;
}
final boolean enabled = !(sharedPrefs.getBoolean(HBM_KEY, false));
FileUtils.writeLine(HBM, enabled ? "1" : "0");
if (enabled) {
FileUtils.writeLine(BACKLIGHT, "2047");
Settings.System.putInt(getContentResolver(), Settings.System.SCREEN_BRIGHTNESS, 255);
}
sharedPrefs.edit().putBoolean(HBM_KEY, enabled).commit();
updateUI(enabled);
}
}

View file

@ -18,6 +18,10 @@ package org.lineageos.settings.utils;
import android.util.Log; import android.util.Log;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
@ -26,6 +30,9 @@ import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import org.lineageos.settings.hbm.HBMFragment;
import org.lineageos.settings.hbm.AutoHBMService;
public final class FileUtils { public final class FileUtils {
private static final String TAG = "FileUtils"; private static final String TAG = "FileUtils";
@ -156,5 +163,38 @@ public final class FileUtils {
Log.e(TAG, "NullPointerException trying to rename " + srcPath + " to " + dstPath, e); Log.e(TAG, "NullPointerException trying to rename " + srcPath + " to " + dstPath, e);
} }
return ok; return ok;
}
public static boolean getFileValueAsBoolean(String filename, boolean defValue) {
String fileValue = readOneLine(filename);
if(fileValue!=null){
return (fileValue.equals("0")?false:true);
}
return defValue;
}
public static String getFileValue(String filename, String defValue) {
String fileValue = readOneLine(filename);
if(fileValue!=null){
return fileValue;
}
return defValue;
}
private static boolean mServiceEnabled = false;
private static void startService(Context context) {
context.startServiceAsUser(new Intent(context, AutoHBMService.class),
UserHandle.CURRENT);
mServiceEnabled = true;
}
private static void stopService(Context context) {
mServiceEnabled = false;
context.stopServiceAsUser(new Intent(context, AutoHBMService.class),
UserHandle.CURRENT);
}
public static void enableService(Context context) {
if (HBMFragment.isAUTOHBMEnabled(context) && !mServiceEnabled) {
startService(context);
} else if (!HBMFragment.isAUTOHBMEnabled(context) && mServiceEnabled) {
stopService(context);
}
} }
} }

View file

@ -220,6 +220,13 @@ on post-fs-data
mkdir /data/vendor/vpp 0770 media media mkdir /data/vendor/vpp 0770 media media
setprop vold.post_fs_data_done 1 setprop vold.post_fs_data_done 1
# Allow system to modify exposure dim layer state
chown system system /sys/devices/platform/soc/soc:qcom,dsi-display-primary/dimlayer_exposure
chmod 0660 /sys/devices/platform/soc/soc:qcom,dsi-display-primary/dimlayer_exposure
# Allow system to modify hbm state
chown system system /sys/devices/platform/soc/soc:qcom,dsi-display-primary/hbm_enabled
chmod 0660 /sys/devices/platform/soc/soc:qcom,dsi-display-primary/hbm_enabled
on property:sys.boot_completed=1 on property:sys.boot_completed=1
# Enable UFS clock scaling back # Enable UFS clock scaling back

View file

@ -1,6 +1,12 @@
# Display # Display
genfscon sysfs /devices/platform/soc/soc:qcom,dsi-display-primary u:object_r:vendor_sysfs_graphics:s0 genfscon sysfs /devices/platform/soc/soc:qcom,dsi-display-primary u:object_r:vendor_sysfs_graphics:s0
# Display dim layer Exposure
genfscon sysfs /devices/platform/soc/soc:qcom,dsi-display-primary/dimlayer_exposure u:object_r:vendor_sysfs_graphics:s0
# Display HBM
genfscon sysfs /sys/devices/platform/soc/soc:qcom,dsi-display-primary/hbm_enabled u:object_r:vendor_sysfs_graphics:s0
# Fingerprint # Fingerprint
genfscon sysfs /devices/platform/soc/soc:fingerprint_fpc u:object_r:vendor_sysfs_fingerprint:s0 genfscon sysfs /devices/platform/soc/soc:fingerprint_fpc u:object_r:vendor_sysfs_fingerprint:s0

View file

@ -1,2 +1,6 @@
allow system_app sysfs_thermal:file write; allow system_app sysfs_thermal:file write;
allow system_app sysfs_thermal:file rw_file_perms; allow system_app sysfs_thermal:file rw_file_perms;
# DC Dimming and HBM
allow system_app vendor_sysfs_graphics:dir search;
allow system_app vendor_sysfs_graphics:file { getattr open write };

View file

@ -0,0 +1,2 @@
allow vendor_hal_perf_default hal_graphics_composer_default:dir search;
allow vendor_hal_perf_default hal_graphics_composer_default:file { open read };