a52sxq: parts: Introduce Display Satutaion Service and TileUtils
* Adjust Saturation Value Handling for Device Color Mode Compatibility This update refines the saturation adjustment mechanism. When the seek bar progress is set, the method executes the command "service call SurfaceFlinger 1022 f [saturation]" via Runtime.getRuntime().exec() to apply the saturation changes. However, it was observed that when the device's color mode is set to "saturated," a saturation value of 1.0 does not trigger any visual changes. To address this, the code now sets a value of 1.001 for a seek bar value of 100, ensuring the desired effect is consistently applied. * TileUtils Implementation: Implemented TileUtils to handle the addition of Quick Settings tiles, specifically for the saturation feature. This is done with reference to the guidelines provided by Google https://developer.android.com/develop/ui/views/quicksettings-tiles#prompt-user this ensuring a seamless integration and user experience when creating new tiles. Change-Id: I77607e993353318f5c75c25ff25342d022aab3a1 Signed-off-by: Pabloescobar-reborn <pabloescobarreborn77@gmail.com> Co-Authored-By: kenway214 <kenway214@outlook.com> Co-Authored-By: AnierinB <anierin@evolution-x.org> Co-Authored-By: SKULSHADY <anushekprasal@gmail.com> Co-Authored-By: jhenrique09 <jhenrique09.mcz@hotmail.com> Signed-off-by: UnmoveD <unmoved2121@gmail.com>
This commit is contained in:
@@ -26,9 +26,9 @@
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.GET_TASKS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_SURFACE_FLINGER" />
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
|
||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" tools:ignore="ProtectedPermissions" />
|
||||
<uses-permission android:name="android.permission.BATTERY_STATS" />
|
||||
@@ -73,6 +73,18 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Thermal Profiles tile service -->
|
||||
<service
|
||||
android:name=".thermal.ThermalTileService"
|
||||
android:label="@string/thermal_tile_label"
|
||||
android:icon="@drawable/ic_thermal_tile"
|
||||
android:permission="android.permission.BIND_QUICK_SETTINGS_TILE"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.service.quicksettings.action.QS_TILE" />
|
||||
</intent-filter>
|
||||
</service>
|
||||
|
||||
<!-- Per-app refresh rate activity -->
|
||||
<activity
|
||||
android:name=".refreshrate.RefreshActivity"
|
||||
@@ -247,5 +259,33 @@
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- Display Saturation activity -->
|
||||
<activity
|
||||
android:name=".saturation.SaturationActivity"
|
||||
android:label="@string/saturation_title"
|
||||
android:exported="true">
|
||||
<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/saturation_summary" />
|
||||
</activity>
|
||||
|
||||
<!-- Display Saturation tile service -->
|
||||
<service
|
||||
android:name=".saturation.SaturationTileService"
|
||||
android:label="@string/saturation_title"
|
||||
android:icon="@drawable/ic_saturation_tile"
|
||||
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>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
BIN
parts/res/drawable-nodpi/image_preview1.jpg
Normal file
BIN
parts/res/drawable-nodpi/image_preview1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
parts/res/drawable-nodpi/image_preview1.webp
Normal file
BIN
parts/res/drawable-nodpi/image_preview1.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 215 KiB |
BIN
parts/res/drawable-nodpi/image_preview2.jpg
Normal file
BIN
parts/res/drawable-nodpi/image_preview2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
BIN
parts/res/drawable-nodpi/image_preview2.webp
Normal file
BIN
parts/res/drawable-nodpi/image_preview2.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 75 KiB |
BIN
parts/res/drawable-nodpi/image_preview3.jpg
Normal file
BIN
parts/res/drawable-nodpi/image_preview3.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 240 KiB |
BIN
parts/res/drawable-nodpi/image_preview3.webp
Normal file
BIN
parts/res/drawable-nodpi/image_preview3.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 187 KiB |
14
parts/res/drawable/ic_custom_seekbar_minus.xml
Normal file
14
parts/res/drawable/ic_custom_seekbar_minus.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018-2022 crDroid Android Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<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="M24 4C12.972 4 4 12.972 4 24s8.972 20 20 20s20 -8.972 20 -20S35.028 4 24 4zM32.5 25.5h-17c-0.829 0 -1.5 -0.671 -1.5 -1.5s0.671 -1.5 1.5 -1.5h17c0.829 0 1.5 0.671 1.5 1.5S33.329 25.5 32.5 25.5z" />
|
||||
</vector>
|
||||
14
parts/res/drawable/ic_custom_seekbar_plus.xml
Normal file
14
parts/res/drawable/ic_custom_seekbar_plus.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018-2022 crDroid Android Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<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="M24 4C12.972 4 4 12.972 4 24s8.972 20 20 20s20 -8.972 20 -20S35.028 4 24 4zM32.5 25.5h-7v7c0 0.829 -0.672 1.5 -1.5 1.5s-1.5 -0.671 -1.5 -1.5v-7h-7c-0.828 0 -1.5 -0.671 -1.5 -1.5s0.672 -1.5 1.5 -1.5h7v-7c0 -0.829 0.672 -1.5 1.5 -1.5s1.5 0.671 1.5 1.5v7h7c0.828 0 1.5 0.671 1.5 1.5S33.328 25.5 32.5 25.5z" />
|
||||
</vector>
|
||||
15
parts/res/drawable/ic_custom_seekbar_reset.xml
Normal file
15
parts/res/drawable/ic_custom_seekbar_reset.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019 Havoc-OS
|
||||
2022 DerpFest
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<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="M14.123456746339798,12.042328000068665 c0,-0.7430335164070133 -0.6079365134239197,-1.3509700298309326 -1.3509700298309326,-1.3509700298309326 s-1.3509700298309326,0.6079365134239197 -1.3509700298309326,1.3509700298309326 s0.6079365134239197,1.3509700298309326 1.3509700298309326,1.3509700298309326 s1.3509700298309326,-0.6079365134239197 1.3509700298309326,-1.3509700298309326 zM12.772486716508865,5.962962865829468 c-3.3571605241298674,0 -6.079365134239197,2.7222046101093293 -6.079365134239197,6.079365134239197 L4.66666653752327,12.042328000068665 l2.7019400596618652,2.7019400596618652 l2.7019400596618652,-2.7019400596618652 L8.044091612100601,12.042328000068665 c0,-2.6141270077228547 2.1142680966854095,-4.728395104408264 4.728395104408264,-4.728395104408264 s4.728395104408264,2.1142680966854095 4.728395104408264,4.728395104408264 s-2.1142680966854095,4.728395104408264 -4.728395104408264,4.728395104408264 c-1.0199823725223542,0 -1.965661393404007,-0.3309876573085789 -2.742469160556793,-0.8781305193901066 l-0.9591887211799618,0.9726984214782719 C10.097566057443618,17.648853623867033 11.380987585783004,18.12169313430786 12.772486716508865,18.12169313430786 c3.3571605241298674,0 6.079365134239197,-2.7222046101093293 6.079365134239197,-6.079365134239197 s-2.7222046101093293,-6.079365134239197 -6.079365134239197,-6.079365134239197 z" />
|
||||
</vector>
|
||||
18
parts/res/drawable/ic_image_preview_arrow_left.xml
Normal file
18
parts/res/drawable/ic_image_preview_arrow_left.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M0,0h24v24h-24z"/>
|
||||
<path
|
||||
android:pathData="M16.41,18.59L15,20L7,12L15,4L16.41,5.41L9.83,12"
|
||||
android:fillColor="?android:attr/colorAccent"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
18
parts/res/drawable/ic_image_preview_arrow_right.xml
Normal file
18
parts/res/drawable/ic_image_preview_arrow_right.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M0,0h24v24h-24z"/>
|
||||
<path
|
||||
android:pathData="M7.59,5.41L9,4L17,12L9,20L7.59,18.59L14.17,12"
|
||||
android:fillColor="?android:attr/colorAccent"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="6dp"
|
||||
android:height="6dp"
|
||||
android:viewportWidth="6"
|
||||
android:viewportHeight="6">
|
||||
<path
|
||||
android:pathData="M3,0C4.65686,0 6,1.34315 6,3C6,4.65686 4.65685,6 3,6C1.34315,6 0,4.65685 0,3C0,1.34315 1.34315,0 3,0Z"
|
||||
android:fillColor="?android:attr/colorAccent"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="6dp"
|
||||
android:height="6dp"
|
||||
android:viewportWidth="6"
|
||||
android:viewportHeight="6">
|
||||
<path
|
||||
android:pathData="M3,0C4.65686,0 6,1.34315 6,3C6,4.65686 4.65685,6 3,6C1.34315,6 0,4.65685 0,3C0,1.34315 1.34315,0 3,0Z"
|
||||
android:fillColor="?android:attr/colorAccent"
|
||||
android:fillAlpha="0.24"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
||||
11
parts/res/drawable/ic_saturation_tile.xml
Normal file
11
parts/res/drawable/ic_saturation_tile.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- drawable/ic_saturation_tile -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="#000"
|
||||
android:pathData="M17.5,12A1.5,1.5 0 0,1 16,10.5A1.5,1.5 0 0,1 17.5,9A1.5,1.5 0 0,1 19,10.5A1.5,1.5 0 0,1 17.5,12M14.5,8A1.5,1.5 0 0,1 13,6.5A1.5,1.5 0 0,1 14.5,5A1.5,1.5 0 0,1 16,6.5A1.5,1.5 0 0,1 14.5,8M9.5,8A1.5,1.5 0 0,1 8,6.5A1.5,1.5 0 0,1 9.5,5A1.5,1.5 0 0,1 11,6.5A1.5,1.5 0 0,1 9.5,8M6.5,12A1.5,1.5 0 0,1 5,10.5A1.5,1.5 0 0,1 6.5,9A1.5,1.5 0 0,1 8,10.5A1.5,1.5 0 0,1 6.5,12M12,3A9,9 0 0,0 3,12A9,9 0 0,0 12,21A1.5,1.5 0 0,0 13.5,19.5C13.5,19.11 13.35,18.76 13.11,18.5C12.88,18.23 12.73,17.88 12.73,17.5A1.5,1.5 0 0,1 14.23,16H16A5,5 0 0,0 21,11C21,6.58 16.97,3 12,3Z" />
|
||||
</vector>
|
||||
11
parts/res/drawable/ic_thermal_tile.xml
Normal file
11
parts/res/drawable/ic_thermal_tile.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?android:attr/colorAccent">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M19.58 9.42l1.54-1.54C21.68 9.14 22 10.53 22 12c0 5.52-4.48 10-10 10S2 17.52 2 12 6.48 2 12 2c1.46 0 2.85 0.32 4.11 0.89l-1.53 1.53C13.77 4.15 12.9 4 12 4c-4.41 0-8 3.59-8 8s3.59 8 8 8 8-3.59 8-8c0-0.9-0.15-1.77-0.42-2.58Zm-8.35 4.43c-0.25-0.1-0.46-0.25-0.65-0.43-0.18-0.19-0.33-0.4-0.43-0.65-0.1-0.24-0.15-0.5-0.15-0.75 0-0.27 0.05-0.52 0.15-0.76 0.1-0.24 0.25-0.46 0.43-0.65L19 5l-5.61 8.42c-0.19 0.18-0.4 0.33-0.65 0.43-0.24 0.1-0.5 0.15-0.76 0.15s-0.51-0.05-0.75-0.15Z"/>
|
||||
</vector>
|
||||
28
parts/res/layout/image_layout.xml
Normal file
28
parts/res/layout/image_layout.xml
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:foregroundGravity="center_horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="320dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:cropToPadding="true"
|
||||
android:contentDescription="@null" />
|
||||
|
||||
</FrameLayout>
|
||||
</LinearLayout>
|
||||
58
parts/res/layout/image_preview_layout.xml
Normal file
58
parts/res/layout/image_preview_layout.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018 The Android Open Source Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.viewpager.widget.ViewPager
|
||||
android:id="@+id/viewpager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="320dp"/>
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/arrow_previous"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:paddingLeft="24dp"
|
||||
android:layout_gravity="center_vertical|left"
|
||||
android:contentDescription="@string/image_preview_previous_page_content_description">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_image_preview_arrow_left"/>
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/viewGroup"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="48dp"
|
||||
android:gravity="center"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/arrow_next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="48dp"
|
||||
android:paddingRight="24dp"
|
||||
android:layout_gravity="center_vertical|right"
|
||||
android:contentDescription="@string/image_preview_next_page_content_description">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/ic_image_preview_arrow_right"/>
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
131
parts/res/layout/preference_custom_seekbar.xml
Normal file
131
parts/res/layout/preference_custom_seekbar.xml
Normal file
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2017-2022 crDroid Android Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<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">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@android:id/icon_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="-4dp"
|
||||
android:minWidth="60dp"
|
||||
android:gravity="start|center_vertical"
|
||||
android:orientation="horizontal"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingBottom="4dp">
|
||||
<com.android.internal.widget.PreferenceImageView
|
||||
android:id="@android:id/icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxWidth="48dp"
|
||||
android:maxHeight="48dp" />
|
||||
</LinearLayout>
|
||||
|
||||
<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>
|
||||
14
parts/res/menu/saturation_menu.xml
Normal file
14
parts/res/menu/saturation_menu.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2021 The Android Open Source Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/add_tile"
|
||||
android:title="@string/tile_add" />
|
||||
</menu>
|
||||
@@ -1,7 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2025 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.
|
||||
-->
|
||||
<resources>
|
||||
<declare-styleable name="MinMaxSeekBarPreference">
|
||||
<attr name="minValue" format="integer" />
|
||||
<attr name="maxValue" format="integer" />
|
||||
</declare-styleable>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
@@ -51,6 +51,13 @@
|
||||
<string name="charging_tile_discharging">Discharging</string>
|
||||
<string name="charging_tile_not_charging">Not Charging</string>
|
||||
<string name="charging_tile_error">Error</string>
|
||||
|
||||
<!-- Thermal Tile Strings -->
|
||||
<string name="thermal_tile_label">Thermal Mode</string>
|
||||
<string name="thermal_mode_default">Default Mode</string>
|
||||
<string name="thermal_mode_performance">Performance Mode</string>
|
||||
<string name="thermal_mode_battery_saver">Battery Saver Mode</string>
|
||||
<string name="thermal_mode_gaming">Gaming Mode</string>
|
||||
|
||||
<!-- Content descriptions for accessibility -->
|
||||
<string name="charging_tile_desc_charging">Charging at %1$s watts, %2$s amps, %3$s volts</string>
|
||||
@@ -94,4 +101,20 @@
|
||||
<string name="charge_bypass_notification_text">Battery charging is currently bypassed</string>
|
||||
<string name="charge_bypass_smart_enabled">Smart charging bypass enabled at %d%%</string>
|
||||
<string name="charge_bypass_smart_disabled">Smart charging bypass disabled</string>
|
||||
|
||||
<!-- Saturation -->
|
||||
<string name="saturation_title">Display Saturation</string>
|
||||
<string name="saturation_summary">Control the saturation level of the display</string>
|
||||
<string name="saturation_footer_summary">Changing the color mode in display settings will override the saturation level, requiring it to be reapplied.</string>
|
||||
|
||||
<!-- Image preview -->
|
||||
<string name="image_preview_content_description">Preview</string>
|
||||
<string name="image_preview_next_page_content_description">Next</string>
|
||||
<string name="image_preview_previous_page_content_description">Previous</string>
|
||||
|
||||
<!-- Custom seekbar -->
|
||||
<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>
|
||||
|
||||
38
parts/res/xml/saturation.xml
Normal file
38
parts/res/xml/saturation.xml
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018-2014 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"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.android.settingslib.widget.LayoutPreference
|
||||
android:key="saturation_preview"
|
||||
android:layout="@layout/image_preview_layout"
|
||||
android:selectable="false" />
|
||||
|
||||
<org.lineageos.settings.CustomSeekBarPreference
|
||||
android:key="saturation"
|
||||
android:max="200"
|
||||
android:min="0"
|
||||
android:defaultValue="100"
|
||||
settings:continuousUpdates="true" />
|
||||
|
||||
<com.android.settingslib.widget.FooterPreference
|
||||
android:key="saturation_footer"
|
||||
android:title="@string/saturation_footer_summary"
|
||||
android:selectable="false" />
|
||||
</PreferenceScreen>
|
||||
@@ -32,6 +32,7 @@ import android.util.Log;
|
||||
import android.view.Display;
|
||||
|
||||
import org.lineageos.settings.refreshrate.RefreshUtils;
|
||||
import org.lineageos.settings.thermal.ThermalTileService;
|
||||
|
||||
public class BootCompletedReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "Parts";
|
||||
|
||||
24
parts/src/org/lineageos/settings/Constants.java
Normal file
24
parts/src/org/lineageos/settings/Constants.java
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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;
|
||||
|
||||
public class Constants {
|
||||
|
||||
// Saturation
|
||||
public static final String KEY_SATURATION = "saturation";
|
||||
public static final String KEY_SATURATION_PREVIEW = "saturation_preview";
|
||||
}
|
||||
368
parts/src/org/lineageos/settings/CustomSeekBarPreference.java
Normal file
368
parts/src/org/lineageos/settings/CustomSeekBarPreference.java
Normal file
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
91
parts/src/org/lineageos/settings/Startup.java
Normal file
91
parts/src/org/lineageos/settings/Startup.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.util.Log;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.lineageos.settings.Constants;
|
||||
import org.lineageos.settings.saturation.SaturationFragment;
|
||||
import org.lineageos.settings.utils.ComponentUtils;
|
||||
import org.lineageos.settings.utils.FileUtils;
|
||||
|
||||
public class Startup extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = "Startup";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
Log.d(TAG, "onReceive called with action: " + action);
|
||||
|
||||
if (Intent.ACTION_BOOT_COMPLETED.equals(action) ||
|
||||
Intent.ACTION_REBOOT.equals(action)) {
|
||||
|
||||
// Adding a delay before applying the saturation
|
||||
new Handler(Looper.getMainLooper()).postDelayed(() -> {
|
||||
Log.d(TAG, "Applying saved saturation setting...");
|
||||
applySavedSaturation(context);
|
||||
}, 5000); // Delay of 5 seconds
|
||||
}
|
||||
}
|
||||
|
||||
private void applySavedSaturation(Context context) {
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
int seekBarValue = sharedPrefs.getInt(Constants.KEY_SATURATION, 100);
|
||||
Log.d(TAG, "Retrieved seekBarValue: " + seekBarValue);
|
||||
|
||||
// Apply the saved saturation value
|
||||
applySaturation(seekBarValue);
|
||||
}
|
||||
|
||||
private void applySaturation(int seekBarValue) {
|
||||
Log.d(TAG, "Applying saturation: " + seekBarValue);
|
||||
|
||||
float saturation;
|
||||
if (seekBarValue == 100) {
|
||||
saturation = 1.001f;
|
||||
} else {
|
||||
saturation = seekBarValue / 100.0f;
|
||||
}
|
||||
|
||||
IBinder surfaceFlinger = ServiceManager.getService("SurfaceFlinger");
|
||||
if (surfaceFlinger != null) {
|
||||
try {
|
||||
Parcel data = Parcel.obtain();
|
||||
data.writeInterfaceToken("android.ui.ISurfaceComposer");
|
||||
data.writeFloat(saturation);
|
||||
surfaceFlinger.transact(1022, data, null, 0);
|
||||
data.recycle();
|
||||
Log.d(TAG, "Saturation applied successfully");
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Failed to apply saturation", e);
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "SurfaceFlinger service not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.saturation;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
|
||||
|
||||
public class SaturationActivity extends CollapsingToolbarBaseActivity {
|
||||
|
||||
private static final String TAG = "Saturation";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getSupportFragmentManager().beginTransaction().replace(com.android.settingslib.collapsingtoolbar.R.id.content_frame,
|
||||
new SaturationFragment(), TAG).commit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.saturation;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceFragmentCompat;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.viewpager.widget.PagerAdapter;
|
||||
import androidx.viewpager.widget.ViewPager;
|
||||
|
||||
import com.android.settingslib.widget.LayoutPreference;
|
||||
|
||||
import org.lineageos.settings.Constants;
|
||||
import org.lineageos.settings.CustomSeekBarPreference;
|
||||
import org.lineageos.settings.R;
|
||||
import org.lineageos.settings.utils.TileUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SaturationFragment extends PreferenceFragmentCompat
|
||||
implements Preference.OnPreferenceChangeListener {
|
||||
|
||||
private View mViewArrowPrevious;
|
||||
private View mViewArrowNext;
|
||||
private ViewPager mViewPager;
|
||||
|
||||
private ImageView[] mDotIndicators;
|
||||
private View[] mViewPagerImages;
|
||||
|
||||
private CustomSeekBarPreference mSaturationPreference;
|
||||
|
||||
private IBinder mSurfaceFlinger;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
setPreferencesFromResource(R.xml.saturation, rootKey);
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
LayoutPreference preview = findPreference(Constants.KEY_SATURATION_PREVIEW);
|
||||
addViewPager(preview);
|
||||
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
|
||||
mSaturationPreference = (CustomSeekBarPreference) findPreference(Constants.KEY_SATURATION);
|
||||
mSaturationPreference.setOnPreferenceChangeListener(this);
|
||||
int seekBarValue = sharedPrefs.getInt(Constants.KEY_SATURATION, 100);
|
||||
updateSaturation(seekBarValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.saturation_menu, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
if (preference == mSaturationPreference) {
|
||||
int seekBarValue = (Integer) newValue;
|
||||
updateSaturation(seekBarValue);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.add_tile) {
|
||||
TileUtils.requestAddTileService(
|
||||
getContext(),
|
||||
SaturationTileService.class,
|
||||
R.string.saturation_title,
|
||||
R.drawable.ic_saturation_tile
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateSaturation(int seekBarValue) {
|
||||
float saturation;
|
||||
if (seekBarValue == 100) {
|
||||
saturation = 1.001f;
|
||||
} else {
|
||||
saturation = seekBarValue / 100.0f;
|
||||
}
|
||||
|
||||
if (mSurfaceFlinger != null) {
|
||||
try {
|
||||
Parcel data = Parcel.obtain();
|
||||
data.writeInterfaceToken("android.ui.ISurfaceComposer");
|
||||
data.writeFloat(saturation);
|
||||
mSurfaceFlinger.transact(1022, data, null, 0);
|
||||
data.recycle();
|
||||
} catch (RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger");
|
||||
}
|
||||
|
||||
public void restoreSaturationSetting(Context context) {
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
int seekBarValue = sharedPrefs.getInt(Constants.KEY_SATURATION, 100);
|
||||
updateSaturation(seekBarValue);
|
||||
}
|
||||
|
||||
void addViewPager(LayoutPreference preview) {
|
||||
mViewPager = preview.findViewById(R.id.viewpager);
|
||||
|
||||
int[] drawables = new int[]{
|
||||
R.drawable.image_preview1,
|
||||
R.drawable.image_preview2,
|
||||
R.drawable.image_preview3
|
||||
};
|
||||
|
||||
mViewPagerImages = new View[drawables.length];
|
||||
|
||||
for (int idx = 0; idx < drawables.length; idx++) {
|
||||
mViewPagerImages[idx] = getLayoutInflater().inflate(R.layout.image_layout, null);
|
||||
ImageView imageView = mViewPagerImages[idx].findViewById(R.id.imageView);
|
||||
imageView.setImageResource(drawables[idx]);
|
||||
}
|
||||
|
||||
mViewPager.setAdapter(new ImagePreviewPagerAdapter(mViewPagerImages));
|
||||
|
||||
mViewArrowPrevious = preview.findViewById(R.id.arrow_previous);
|
||||
mViewArrowPrevious.setOnClickListener(v -> mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1, true));
|
||||
|
||||
mViewArrowNext = preview.findViewById(R.id.arrow_next);
|
||||
mViewArrowNext.setOnClickListener(v -> mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1, true));
|
||||
|
||||
mViewPager.addOnPageChangeListener(createPageListener());
|
||||
|
||||
final ViewGroup viewGroup = preview.findViewById(R.id.viewGroup);
|
||||
mDotIndicators = new ImageView[mViewPagerImages.length];
|
||||
for (int i = 0; i < mViewPagerImages.length; i++) {
|
||||
final ImageView imageView = new ImageView(getContext());
|
||||
final ViewGroup.MarginLayoutParams lp =
|
||||
new ViewGroup.MarginLayoutParams(12, 12);
|
||||
lp.setMargins(6, 0, 6, 0);
|
||||
imageView.setLayoutParams(lp);
|
||||
mDotIndicators[i] = imageView;
|
||||
|
||||
viewGroup.addView(mDotIndicators[i]);
|
||||
}
|
||||
|
||||
updateIndicator(mViewPager.getCurrentItem());
|
||||
}
|
||||
|
||||
private ViewPager.OnPageChangeListener createPageListener() {
|
||||
return new ViewPager.OnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageScrolled(
|
||||
int position, float positionOffset, int positionOffsetPixels) {
|
||||
if (positionOffset != 0) {
|
||||
for (View mViewPagerImage : mViewPagerImages) {
|
||||
mViewPagerImage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else {
|
||||
mViewPagerImages[position].setContentDescription(
|
||||
getContext().getString(R.string.image_preview_content_description));
|
||||
updateIndicator(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrollStateChanged(int state) {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void updateIndicator(int position) {
|
||||
for (int i = 0; i < mViewPagerImages.length; i++) {
|
||||
if (position == i) {
|
||||
mDotIndicators[i].setBackgroundResource(
|
||||
R.drawable.ic_image_preview_page_indicator_focused);
|
||||
|
||||
mViewPagerImages[i].setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mDotIndicators[i].setBackgroundResource(
|
||||
R.drawable.ic_image_preview_page_indicator_unfocused);
|
||||
|
||||
mViewPagerImages[i].setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
if (position == 0) {
|
||||
mViewArrowPrevious.setVisibility(View.INVISIBLE);
|
||||
mViewArrowNext.setVisibility(View.VISIBLE);
|
||||
} else if (position == (mViewPagerImages.length - 1)) {
|
||||
mViewArrowPrevious.setVisibility(View.VISIBLE);
|
||||
mViewArrowNext.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
mViewArrowPrevious.setVisibility(View.VISIBLE);
|
||||
mViewArrowNext.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
static class ImagePreviewPagerAdapter extends PagerAdapter {
|
||||
private final View[] mPageViewList;
|
||||
|
||||
ImagePreviewPagerAdapter(View[] pageViewList) {
|
||||
mPageViewList = pageViewList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyItem(ViewGroup container, int position, Object object) {
|
||||
if (mPageViewList[position] != null) {
|
||||
container.removeView(mPageViewList[position]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object instantiateItem(ViewGroup container, int position) {
|
||||
container.addView(mPageViewList[position]);
|
||||
return mPageViewList[position];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mPageViewList.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewFromObject(View view, Object object) {
|
||||
return object == view;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2024 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.saturation;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Intent;
|
||||
import android.service.quicksettings.Tile;
|
||||
import android.service.quicksettings.TileService;
|
||||
|
||||
public class SaturationTileService extends TileService {
|
||||
|
||||
@Override
|
||||
public void onStartListening() {
|
||||
super.onStartListening();
|
||||
updateTile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
super.onClick();
|
||||
Intent intent = new Intent(this, SaturationActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
PendingIntent pendingIntent = PendingIntent.getActivity(
|
||||
this,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
);
|
||||
startActivityAndCollapse(pendingIntent);
|
||||
}
|
||||
|
||||
private void updateTile() {
|
||||
final Tile tile = getQsTile();
|
||||
tile.setState(Tile.STATE_ACTIVE);
|
||||
tile.updateTile();
|
||||
}
|
||||
}
|
||||
108
parts/src/org/lineageos/settings/thermal/ThermalTileService.java
Normal file
108
parts/src/org/lineageos/settings/thermal/ThermalTileService.java
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.thermal;
|
||||
|
||||
import android.service.quicksettings.TileService;
|
||||
import android.service.quicksettings.Tile;
|
||||
import android.util.Log;
|
||||
|
||||
import org.lineageos.settings.utils.FileUtils;
|
||||
import org.lineageos.settings.utils.TileUtils;
|
||||
import org.lineageos.settings.R;
|
||||
|
||||
public class ThermalTileService extends TileService {
|
||||
|
||||
private static final String TAG = "ThermalTileService";
|
||||
private static final String THERMAL_SCONFIG = "/sys/class/thermal/thermal_message/sconfig";
|
||||
|
||||
private String[] modes;
|
||||
private int currentMode = 0; // Default to the first mode
|
||||
|
||||
@Override
|
||||
public void onStartListening() {
|
||||
super.onStartListening();
|
||||
modes = new String[]{
|
||||
getString(R.string.thermal_mode_default),
|
||||
getString(R.string.thermal_mode_performance),
|
||||
getString(R.string.thermal_mode_battery_saver),
|
||||
getString(R.string.thermal_mode_gaming)
|
||||
};
|
||||
currentMode = getCurrentThermalMode();
|
||||
|
||||
// If sconfig value is -1 or invalid, set it to default mode
|
||||
if (currentMode == -1) {
|
||||
currentMode = 0; // Default mode
|
||||
setThermalMode(0); // Write default mode value to sconfig
|
||||
}
|
||||
|
||||
updateTile(); // Ensure the tile displays the correct mode when added to quick settings
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
toggleThermalMode();
|
||||
}
|
||||
|
||||
private void toggleThermalMode() {
|
||||
currentMode = (currentMode + 1) % modes.length; // Cycle through modes
|
||||
setThermalMode(currentMode);
|
||||
updateTile();
|
||||
}
|
||||
|
||||
private int getCurrentThermalMode() {
|
||||
String line = FileUtils.readOneLine(THERMAL_SCONFIG);
|
||||
if (line != null) {
|
||||
try {
|
||||
int value = Integer.parseInt(line.trim());
|
||||
switch (value) {
|
||||
case 20: return 0; // Default
|
||||
case 10: return 1; // Performance
|
||||
case 3: return 2; // Battery Saver
|
||||
case 9: return 3; // Gaming
|
||||
default: return 0; // Default if unknown value
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "Error parsing thermal mode value: ", e);
|
||||
}
|
||||
}
|
||||
return -1; // Indicate invalid or unknown mode
|
||||
}
|
||||
|
||||
private void setThermalMode(int mode) {
|
||||
int thermalValue;
|
||||
switch (mode) {
|
||||
case 0: thermalValue = 20; break; // Default
|
||||
case 1: thermalValue = 10; break; // Performance
|
||||
case 2: thermalValue = 3; break; // Battery Saver
|
||||
case 3: thermalValue = 9; break; // Gaming
|
||||
default: thermalValue = 20; break; // Default
|
||||
}
|
||||
|
||||
// Write the new thermal value to the sconfig file
|
||||
boolean success = FileUtils.writeLine(THERMAL_SCONFIG, String.valueOf(thermalValue));
|
||||
Log.d(TAG, "Thermal mode changed to " + modes[mode] + ": " + success);
|
||||
}
|
||||
|
||||
private void updateTile() {
|
||||
Tile tile = getQsTile();
|
||||
if (tile != null) {
|
||||
tile.setLabel("Thermal Profile"); // Set the main label
|
||||
tile.setSubtitle(modes[currentMode]); // Set the current mode as the subtitle
|
||||
tile.updateTile();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user