PixelParts: Initial commit
This branch will ONLY be configured for pixel 6 & 7 series. Co-authored-by: Pranav Vashi <neobuddy89@gmail.com> Co-authored-by: LorDClockaN <lordclockan@gmail.com> Co-authored-by: AmeChanRain <downloadbot007@gmail.com> Co-authored-by: Ramii Ahmed <ramy@ahmedramy.com> Co-authored-by: Max Weninger <max.weninger@gmail.com> Co-authored-by: Hikari-no-Tenshi <kyryljan.serhij@gmail.com> Co-authored-by: EmanuelCN <emanuelghub@gmail.com> Signed-off-by: AnierinB <anierin@evolution-x.org>
This commit is contained in:
35
Android.bp
Normal file
35
Android.bp
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright (C) 2023 The Evolution X Project
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
android_app {
|
||||
name: "PixelParts",
|
||||
defaults: [
|
||||
"SettingsLibDefaults",
|
||||
],
|
||||
srcs: [
|
||||
"src/**/*.java",
|
||||
"src/**/*.kt",
|
||||
],
|
||||
certificate: "platform",
|
||||
platform_apis: true,
|
||||
system_ext_specific: true,
|
||||
privileged: true,
|
||||
static_libs: [
|
||||
"androidx.core_core",
|
||||
"androidx.preference_preference",
|
||||
"particles",
|
||||
],
|
||||
resource_dirs: ["res"],
|
||||
optimize: {
|
||||
proguard_flags_files: ["proguard.flags"],
|
||||
},
|
||||
}
|
||||
|
||||
java_import {
|
||||
name: "particles",
|
||||
jars: [
|
||||
"libs/LeonidsLib.jar",
|
||||
],
|
||||
}
|
||||
131
AndroidManifest.xml
Normal file
131
AndroidManifest.xml
Normal file
@@ -0,0 +1,131 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2023 The Evolution X Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:sharedUserId="android.uid.system"
|
||||
package="org.evolution.pixelparts"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0" >
|
||||
|
||||
<uses-permission android:name="android.permission.INJECT_EVENTS"/>
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
|
||||
|
||||
<application
|
||||
android:icon="@drawable/ic_launcher_settings"
|
||||
android:label="@string/pixel_parts_title"
|
||||
android:defaultToDeviceProtectedStorage="true"
|
||||
android:directBootAware="true"
|
||||
android:theme="@style/Theme.SubSettingsBase"
|
||||
android:exported="true">
|
||||
|
||||
<provider
|
||||
android:name="androidx.startup.InitializationProvider"
|
||||
android:authorities="${applicationId}.androidx-startup"
|
||||
tools:replace="android:authorities"/>
|
||||
|
||||
<!-- PixelParts -->
|
||||
<activity
|
||||
android:name=".PixelPartsActivity"
|
||||
android:label="@string/pixel_parts_title"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="com.android.settings.action.EXTRA_SETTINGS" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="com.android.settings.icon"
|
||||
android:resource="@drawable/ic_pixel_parts" />
|
||||
<meta-data
|
||||
android:name="com.android.settings.category"
|
||||
android:value="com.android.settings.category.ia.homepage" />
|
||||
<meta-data android:name="com.android.settings.summary"
|
||||
android:resource="@string/pixel_parts_summary" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".PixelParts"
|
||||
android:exported="false" />
|
||||
|
||||
<!-- PixelParts boot completed receiver -->
|
||||
<receiver
|
||||
android:name=".Startup"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<!-- HBM service -->
|
||||
<service
|
||||
android:name=".services.HBMService"
|
||||
android:exported="false" />
|
||||
|
||||
<!-- Auto HBM service -->
|
||||
<service
|
||||
android:name=".services.AutoHBMService"
|
||||
android:exported="false" />
|
||||
|
||||
<!-- Jitter test activity -->
|
||||
<activity
|
||||
android:name=".uibench.JitterTestActivity"
|
||||
android:label="@string/jitter_test_title"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Power efficient workqueue tile service -->
|
||||
<service
|
||||
android:name=".services.PEWQTileSerice"
|
||||
android:label="@string/power_efficient_workqueue_title"
|
||||
android:icon="@drawable/ic_power_efficient_workqueue_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>
|
||||
|
||||
<!-- HBM tile service -->
|
||||
<service
|
||||
android:name=".services.HBMTileService"
|
||||
android:label="@string/hbm_title"
|
||||
android:icon="@drawable/ic_hbm_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>
|
||||
|
||||
<!-- USB 2.0 Fastcharge tile service -->
|
||||
<service
|
||||
android:name=".services.USB2FCTileService"
|
||||
android:label="@string/usb2_fast_charge_title"
|
||||
android:icon="@drawable/ic_usb2_fc_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>
|
||||
|
||||
<!-- Search Provider -->
|
||||
<provider
|
||||
android:name=".ConfigPanelSearchIndexablesProvider"
|
||||
android:authorities="org.evolution.pixelparts"
|
||||
android:multiprocess="false"
|
||||
android:grantUriPermissions="true"
|
||||
android:permission="android.permission.READ_SEARCH_INDEXABLES"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.content.action.SEARCH_INDEXABLES_PROVIDER" />
|
||||
</intent-filter>
|
||||
</provider>
|
||||
</application>
|
||||
</manifest>
|
||||
3
crowdin.yml
Normal file
3
crowdin.yml
Normal file
@@ -0,0 +1,3 @@
|
||||
files:
|
||||
- source: /**/values/strings.xml
|
||||
translation: /%original_path%-%android_code%/%original_file_name%
|
||||
10
device.mk
Normal file
10
device.mk
Normal file
@@ -0,0 +1,10 @@
|
||||
# PixelParts app
|
||||
PRODUCT_PACKAGES += \
|
||||
PixelParts
|
||||
|
||||
# PixelParts sepolicy
|
||||
BOARD_SEPOLICY_DIRS += packages/apps/PixelParts/sepolicy
|
||||
|
||||
# PixelParts init rc
|
||||
PRODUCT_COPY_FILES += \
|
||||
packages/apps/PixelParts/init/init.pixelparts.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/init.pixelparts.rc
|
||||
13
init/init.pixelparts.rc
Normal file
13
init/init.pixelparts.rc
Normal file
@@ -0,0 +1,13 @@
|
||||
on property:sys.boot_completed=1
|
||||
|
||||
# Power Efficient Workqueue
|
||||
chown system system /sys/module/workqueue/parameters/power_efficient
|
||||
chmod 0666 /sys/module/workqueue/parameters/power_efficient
|
||||
|
||||
# HBM
|
||||
chown system system /sys/class/backlight/panel0-backlight/hbm_mode
|
||||
chmod 0666 /sys/class/backlight/panel0-backlight/hbm_mode
|
||||
|
||||
# USB 2.0 Force Fast Charge
|
||||
chown system system /sys/kernel/fast_charge/force_fast_charge
|
||||
chmod 0666 /sys/kernel/fast_charge/force_fast_charge
|
||||
BIN
libs/LeonidsLib.jar
Normal file
BIN
libs/LeonidsLib.jar
Normal file
Binary file not shown.
3
proguard.flags
Normal file
3
proguard.flags
Normal file
@@ -0,0 +1,3 @@
|
||||
-keep class org.evolution.pixelparts.** {
|
||||
*;
|
||||
}
|
||||
19
res/drawable/easteregg.xml
Normal file
19
res/drawable/easteregg.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2019-2023 The Evolution X Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="48dp"
|
||||
android:height="48dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#005eff"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M15,24c-0.2,0 -0.5,-0.1 -0.6,-0.2L4.1,14.7c-0.3,-0.2 -0.4,-0.6 -0.3,-1l0.9,-3.4c0.1,-0.4 0.5,-0.7 0.9,-0.7h10.1c0.3,0 0.6,0.1 0.7,0.4l2.8,3.4c0.2,0.3 0.3,0.7 0.1,1c-0.2,0.3 -0.5,0.5 -0.9,0.5h-5.8l3.8,3.4c0.3,0.2 0.4,0.6 0.3,0.9l-0.9,4c-0.1,0.3 -0.3,0.6 -0.6,0.7C15.2,24 15.1,24 15,24zM5.8,13.7l8.6,7.6l0.4,-1.9l-5.3,-4.7c-0.3,-0.3 -0.4,-0.7 -0.3,-1.1c0.1,-0.4 0.5,-0.6 0.9,-0.6h6.4l-1.2,-1.5H6.4L5.8,13.7z" />
|
||||
<path
|
||||
android:fillColor="#005eff"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M17.6,7.4H8.9c-0.2,0 -0.5,-0.1 -0.7,-0.3L4.6,3.7C4.3,3.4 4.2,3 4.3,2.6C4.5,2.2 4.8,2 5.2,2h13.3c0.3,0 0.6,0.1 0.8,0.4c0.2,0.2 0.2,0.5 0.2,0.8l-0.9,3.4C18.4,7.1 18,7.4 17.6,7.4zM9.3,5.4h7.6l0.4,-1.5H7.6L9.3,5.4z" />
|
||||
</vector>
|
||||
14
res/drawable/ic_custom_seekbar_minus.xml
Normal file
14
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
res/drawable/ic_custom_seekbar_plus.xml
Normal file
14
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
res/drawable/ic_custom_seekbar_reset.xml
Normal file
15
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>
|
||||
11
res/drawable/ic_hbm_tile.xml
Normal file
11
res/drawable/ic_hbm_tile.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- drawable/ic_hbm_tile.xml -->
|
||||
<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>
|
||||
11
res/drawable/ic_info_outline.xml
Normal file
11
res/drawable/ic_info_outline.xml
Normal 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>
|
||||
5
res/drawable/ic_launcher_settings.xml
Normal file
5
res/drawable/ic_launcher_settings.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/icon_launcher_setting_color"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_settings"/>
|
||||
</adaptive-icon>
|
||||
10
res/drawable/ic_pixel_parts.xml
Normal file
10
res/drawable/ic_pixel_parts.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<!-- drawable/ic_pixel_parts.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="?android:attr/colorPrimary"
|
||||
android:pathData="M21.81 12.74l-0.82 -0.63c0 -0.09 0 -0.13 0 -0.22l0.8 -0.63c0.16 -0.12 0.2 -0.34 0.1 -0.51l-0.85 -1.48c-0.07 -0.13 -0.21 -0.2 -0.35 -0.2c-0.05 0 -0.1 0.01 -0.15 0.03l-0.95 0.38c-0.08 -0.05 -0.11 -0.07 -0.19 -0.11l-0.15 -1.01C19.22 8.15 19.05 8 18.85 8h-1.71c-0.2 0 -0.37 0.15 -0.4 0.34L16.6 9.35c-0.03 0.02 -0.07 0.03 -0.1 0.05c-0.03 0.02 -0.06 0.04 -0.09 0.06l-0.95 -0.38c-0.05 -0.02 -0.1 -0.03 -0.15 -0.03c-0.14 0 -0.27 0.07 -0.35 0.2l-0.85 1.48c-0.1 0.17 -0.06 0.39 0.1 0.51l0.8 0.63c0 0.09 0 0.13 0 0.23l-0.8 0.63c-0.16 0.12 -0.2 0.34 -0.1 0.51l0.85 1.48c0.07 0.13 0.21 0.2 0.35 0.2c0.05 0 0.1 -0.01 0.15 -0.03l0.95 -0.37c0.08 0.05 0.12 0.07 0.2 0.11l0.15 1.01c0.03 0.2 0.2 0.34 0.4 0.34h1.71c0.2 0 0.37 -0.15 0.4 -0.34l0.15 -1.01c0.03 -0.02 0.07 -0.03 0.1 -0.05c0.03 -0.02 0.06 -0.04 0.09 -0.06l0.95 0.38c0.05 0.02 0.1 0.03 0.15 0.03c0.14 0 0.27 -0.07 0.35 -0.2l0.85 -1.48C22.01 13.08 21.97 12.86 21.81 12.74zM18 13.5c-0.83 0 -1.5 -0.67 -1.5 -1.5c0 -0.83 0.67 -1.5 1.5 -1.5s1.5 0.67 1.5 1.5C19.5 12.83 18.83 13.5 18 13.5zM17 18H7V6h10v1h2V3c0 -1.1 -0.9 -2 -2 -2H7C5.9 1 5 1.9 5 3v18c0 1.1 0.9 2 2 2h10c1.1 0 2 -0.9 2 -2v-4h-2V18zM7 3h10v1H7V3zM17 21H7v-1h10V21z" />
|
||||
</vector>
|
||||
11
res/drawable/ic_power_efficient_workqueue_tile.xml
Normal file
11
res/drawable/ic_power_efficient_workqueue_tile.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- drawable/ic_power_efficient_workqueue.xml -->
|
||||
<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="M600,840L600,720L440,720L440,320L360,320L360,440L80,440L80,120L360,120L360,240L600,240L600,120L880,120L880,440L600,440L600,320L520,320L520,640L600,640L600,520L880,520L880,840L600,840ZM160,200L160,200L160,360L160,360L160,200ZM680,600L680,600L680,760L680,760L680,600ZM680,200L680,200L680,360L680,360L680,200ZM680,360L800,360L800,200L680,200L680,360ZM680,760L800,760L800,600L680,600L680,760ZM160,360L280,360L280,200L160,200L160,360Z"/>
|
||||
</vector>
|
||||
11
res/drawable/ic_usb2_fc_tile.xml
Normal file
11
res/drawable/ic_usb2_fc_tile.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<!-- drawable/ic_usb2_fc_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="M23,11H20V4L15,14H18V22M12,8H4V6H12M12.67,4H11V2H5V4H3.33A1.33,1.33 0 0,0 2,5.33V20.67C2,21.4 2.6,22 3.33,22H12.67C13.4,22 14,21.4 14,20.67V5.33A1.33,1.33 0 0,0 12.67,4Z" />
|
||||
</vector>
|
||||
131
res/layout/preference_custom_seekbar.xml
Normal file
131
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>
|
||||
44
res/layout/rendering_jitter.xml
Normal file
44
res/layout/rendering_jitter.xml
Normal file
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016 The Android Open Source 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="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView android:id="@+id/jitter_mma"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
|
||||
<TextView android:id="@+id/totalish_mma"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
|
||||
<TextView android:id="@+id/ui_frametime_mma"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
|
||||
<TextView android:id="@+id/rt_frametime_mma"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
|
||||
<TextView android:id="@+id/total_mma"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true" />
|
||||
|
||||
<View android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<view class="org.evolution.pixelparts.uibench.JitterTestActivity$PointGraphView"
|
||||
android:id="@+id/graph"
|
||||
android:layout_height="200dp"
|
||||
android:layout_width="match_parent" />
|
||||
</LinearLayout>
|
||||
BIN
res/mipmap-hdpi/ic_launcher_settings.png
Normal file
BIN
res/mipmap-hdpi/ic_launcher_settings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
BIN
res/mipmap-mdpi/ic_launcher_settings.png
Normal file
BIN
res/mipmap-mdpi/ic_launcher_settings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.3 KiB |
BIN
res/mipmap-xhdpi/ic_launcher_settings.png
Normal file
BIN
res/mipmap-xhdpi/ic_launcher_settings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
res/mipmap-xxhdpi/ic_launcher_settings.png
Normal file
BIN
res/mipmap-xxhdpi/ic_launcher_settings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
BIN
res/mipmap-xxxhdpi/ic_launcher_settings.png
Normal file
BIN
res/mipmap-xxxhdpi/ic_launcher_settings.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 28 KiB |
17
res/values/attrs.xml
Normal file
17
res/values/attrs.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2018-2022 crDroid Android Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<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>
|
||||
12
res/values/colors.xml
Normal file
12
res/values/colors.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2016-2022 crDroid Android Project
|
||||
2023 The Evolution X Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<color name="icon_launcher_setting_color">@*android:color/accent_device_default_light</color>
|
||||
<color name="disabled_text_color">#66000000</color> <!-- 38% black -->
|
||||
|
||||
</resources>
|
||||
48
res/values/strings.xml
Normal file
48
res/values/strings.xml
Normal file
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2023 The Evolution X Project
|
||||
2016-2022 crDroid Android Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
|
||||
|
||||
<!-- PixelParts -->
|
||||
<string name="pixel_parts_title">Pixel Parts</string>
|
||||
<string name="pixel_parts_summary">Configure device specific settings</string>
|
||||
<string name="pixel_parts_warning_title">Warning</string>
|
||||
<string name="pixel_parts_warning_text">Most of these features rely on specific kernel nodes in order to function. When flashing a custom kernel, you risk the possibility of losing access to some of these features. You have been warned!</string>
|
||||
<string name="pixel_parts_dialog">OK</string>
|
||||
|
||||
<!-- CPU -->
|
||||
<string name="category_cpu">CPU</string>
|
||||
<string name="power_efficient_workqueue_title">Power efficient workqueue</string>
|
||||
<string name="power_efficient_workqueue_summary">Save power by rescheduling work to a core that is already awake</string>
|
||||
|
||||
<!-- Display -->
|
||||
<string name="category_display">Display</string>
|
||||
<string name="hbm_title">High brightness mode (HBM)</string>
|
||||
<string name="hbm_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_info">Long time usage of High brightness mode may damage your display!</string>
|
||||
|
||||
<!-- UiBench -->
|
||||
<string name="category_uibench">UiBench</string>
|
||||
<string name="jitter_test_title">Jitter</string>
|
||||
<string name="jitter_test_summary">Calculate rendering jitter</string>
|
||||
|
||||
<!-- USB -->
|
||||
<string name="category_usb">USB</string>
|
||||
<string name="usb2_fast_charge_title">USB 2.0 fast charge</string>
|
||||
<string name="usb2_fast_charge_summary">Enable CDP mode for fast charging on USB 2.0 ports</string>
|
||||
<string name="usb2_fast_charge_info">Not all USB 2.0 ports support CDP mode, use with caution!</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>
|
||||
84
res/xml/main.xml
Normal file
84
res/xml/main.xml
Normal file
@@ -0,0 +1,84 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2023 The Evolution X Project
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
-->
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res/org.evolution.pixelparts">
|
||||
|
||||
<com.android.settingslib.widget.TopIntroPreference
|
||||
android:key="pixel_parts_intro"
|
||||
android:title="@string/pixel_parts_summary"/>
|
||||
|
||||
<!-- Start of CPU category -->
|
||||
<PreferenceCategory
|
||||
android:key="category_cpu"
|
||||
android:title="@string/category_cpu">
|
||||
|
||||
<SwitchPreference
|
||||
android:key="power_efficient_workqueue"
|
||||
android:title="@string/power_efficient_workqueue_title"
|
||||
android:summary="@string/power_efficient_workqueue_summary" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<!-- Start of display category -->
|
||||
<PreferenceCategory
|
||||
android:key="category_display"
|
||||
android:title="@string/category_display">
|
||||
|
||||
<SwitchPreference
|
||||
android:key="hbm"
|
||||
android:title="@string/hbm_title"
|
||||
android:summary="@string/hbm_summary" />
|
||||
|
||||
<SwitchPreference
|
||||
android:key="auto_hbm"
|
||||
android:title="@string/auto_hbm_title"
|
||||
android:summary="@string/auto_hbm_summary" />
|
||||
|
||||
<org.evolution.pixelparts.preferences.AutoHBMThresholdPreference
|
||||
android:key="auto_hbm_threshold"
|
||||
android:dependency="auto_hbm"
|
||||
android:title="@string/auto_hbm_threshold_title"
|
||||
android:summary="@string/auto_hbm_threshold_summary" />
|
||||
|
||||
<Preference
|
||||
android:key="hbm_info"
|
||||
android:icon="@drawable/ic_info_outline"
|
||||
android:summary="@string/hbm_info"
|
||||
android:persistent="false" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<!-- Start of UiBench Category -->
|
||||
<PreferenceCategory
|
||||
android:key="category_uibench"
|
||||
android:title="@string/category_uibench">
|
||||
|
||||
<Preference
|
||||
android:key="jitter"
|
||||
android:title="@string/jitter_test_title"
|
||||
android:summary="@string/jitter_test_summary"
|
||||
android:persistent="false" >
|
||||
<intent android:action="android.intent.action.MAIN"
|
||||
android:targetPackage="org.evolution.pixelparts"
|
||||
android:targetClass="org.evolution.pixelparts.uibench.JitterTestActivity" />
|
||||
</Preference>
|
||||
</PreferenceCategory>
|
||||
|
||||
<!-- Start of usb category -->
|
||||
<PreferenceCategory
|
||||
android:key="category_usb"
|
||||
android:title="@string/category_usb">
|
||||
|
||||
<SwitchPreference
|
||||
android:key="usb2_fast_charge"
|
||||
android:title="@string/usb2_fast_charge_title"
|
||||
android:summary="@string/usb2_fast_charge_summary" />
|
||||
|
||||
<Preference
|
||||
android:key="usb2_fast_charge_info"
|
||||
android:icon="@drawable/ic_info_outline"
|
||||
android:summary="@string/usb2_fast_charge_info"
|
||||
android:persistent="false" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
5
sepolicy/file.te
Normal file
5
sepolicy/file.te
Normal file
@@ -0,0 +1,5 @@
|
||||
# USB 2.0 force fast charge
|
||||
type sysfs_fastcharge, fs_type, sysfs_type;
|
||||
|
||||
# Workqueue
|
||||
type sysfs_workqueue, fs_type, sysfs_type;
|
||||
2
sepolicy/file_contexts
Normal file
2
sepolicy/file_contexts
Normal file
@@ -0,0 +1,2 @@
|
||||
/sys/kernel/fast_charge/force_fast_charge u:object_r:sysfs_fastcharge:s0
|
||||
/sys/module/workqueue/parameters/power_efficient u:object_r:sysfs_workqueue:s0
|
||||
33
sepolicy/pixelparts_app.te
Normal file
33
sepolicy/pixelparts_app.te
Normal file
@@ -0,0 +1,33 @@
|
||||
type pixelparts_app, domain;
|
||||
typeattribute pixelparts_app mlstrustedsubject;
|
||||
|
||||
app_domain(pixelparts_app)
|
||||
|
||||
allow pixelparts_app {
|
||||
activity_service
|
||||
activity_task_service
|
||||
audio_service
|
||||
autofill_service
|
||||
content_capture_service
|
||||
game_service
|
||||
gpu_service
|
||||
hint_service
|
||||
media_session_service
|
||||
netstats_service
|
||||
permission_checker_service
|
||||
surfaceflinger_service
|
||||
}:service_manager find;
|
||||
|
||||
allow pixelparts_app system_app_data_file:dir create_dir_perms;
|
||||
allow pixelparts_app system_app_data_file:{ file lnk_file } create_file_perms;
|
||||
allow pixelparts_app system_data_file:dir search;
|
||||
|
||||
allow pixelparts_app {
|
||||
sysfs_fastcharge
|
||||
sysfs_leds
|
||||
sysfs_workqueue
|
||||
}:file rw_file_perms;
|
||||
|
||||
allow pixelparts_app {
|
||||
sysfs_leds
|
||||
}:dir r_dir_perms;
|
||||
1
sepolicy/seapp_contexts
Normal file
1
sepolicy/seapp_contexts
Normal file
@@ -0,0 +1 @@
|
||||
user=system seinfo=platform name=org.evolution.pixelparts domain=pixelparts_app type=system_app_data_file
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod project
|
||||
* 2017 The LineageOS Project
|
||||
* 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts;
|
||||
|
||||
import android.database.Cursor;
|
||||
import android.database.MatrixCursor;
|
||||
import android.provider.SearchIndexableResource;
|
||||
import android.provider.SearchIndexablesProvider;
|
||||
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_CLASS_NAME;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_ICON_RESID;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_ACTION;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RANK;
|
||||
import static android.provider.SearchIndexablesContract.COLUMN_INDEX_XML_RES_RESID;
|
||||
import static android.provider.SearchIndexablesContract.INDEXABLES_RAW_COLUMNS;
|
||||
import static android.provider.SearchIndexablesContract.INDEXABLES_XML_RES_COLUMNS;
|
||||
import static android.provider.SearchIndexablesContract.NON_INDEXABLES_KEYS_COLUMNS;
|
||||
|
||||
public class ConfigPanelSearchIndexablesProvider extends SearchIndexablesProvider {
|
||||
private static final String TAG = "ConfigPanelSearchIndexablesProvider";
|
||||
|
||||
public static final int SEARCH_IDX_BUTTON_PANEL = 0;
|
||||
public static final int SEARCH_IDX_GESTURE_PANEL = 1;
|
||||
public static final int SEARCH_IDX_OCLICK_PANEL = 2;
|
||||
|
||||
private static SearchIndexableResource[] INDEXABLE_RES = new SearchIndexableResource[]{
|
||||
new SearchIndexableResource(1, R.xml.main,
|
||||
PixelPartsActivity.class.getName(),
|
||||
R.drawable.ic_pixel_parts),
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean onCreate() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryXmlResources(String[] projection) {
|
||||
MatrixCursor cursor = new MatrixCursor(INDEXABLES_XML_RES_COLUMNS);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
private static Object[] generateResourceRef(SearchIndexableResource sir) {
|
||||
Object[] ref = new Object[7];
|
||||
ref[COLUMN_INDEX_XML_RES_RANK] = sir.rank;
|
||||
ref[COLUMN_INDEX_XML_RES_RESID] = sir.xmlResId;
|
||||
ref[COLUMN_INDEX_XML_RES_CLASS_NAME] = null;
|
||||
ref[COLUMN_INDEX_XML_RES_ICON_RESID] = sir.iconResId;
|
||||
ref[COLUMN_INDEX_XML_RES_INTENT_ACTION] = "com.android.settings.action.EXTRA_SETTINGS";
|
||||
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_PACKAGE] = "org.evolution.pixelparts;";
|
||||
ref[COLUMN_INDEX_XML_RES_INTENT_TARGET_CLASS] = sir.className;
|
||||
return ref;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryRawData(String[] projection) {
|
||||
MatrixCursor cursor = new MatrixCursor(INDEXABLES_RAW_COLUMNS);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor queryNonIndexableKeys(String[] projection) {
|
||||
MatrixCursor cursor = new MatrixCursor(NON_INDEXABLES_KEYS_COLUMNS);
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
188
src/org/evolution/pixelparts/PixelParts.java
Normal file
188
src/org/evolution/pixelparts/PixelParts.java
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 crDroid Android Project
|
||||
* 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import androidx.preference.PreferenceFragment;
|
||||
import androidx.preference.PreferenceManager;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import org.evolution.pixelparts.misc.Constants;
|
||||
import org.evolution.pixelparts.R;
|
||||
import org.evolution.pixelparts.services.HBMService;
|
||||
import org.evolution.pixelparts.utils.AutoHBMUtils;
|
||||
import org.evolution.pixelparts.utils.Utils;
|
||||
|
||||
public class PixelParts extends PreferenceFragment
|
||||
implements Preference.OnPreferenceChangeListener {
|
||||
private static final String TAG = PixelParts.class.getSimpleName();
|
||||
|
||||
// Power efficient workqueue switch
|
||||
private SwitchPreference mPowerEfficientWorkqueueModeSwitch;
|
||||
|
||||
// High brightness mode switches
|
||||
private SwitchPreference mHBMSwitch;
|
||||
private SwitchPreference mAutoHBMSwitch;
|
||||
|
||||
// USB 2.0 fast charge switch
|
||||
private SwitchPreference mUSB2FastChargeSwitch;
|
||||
|
||||
@Override
|
||||
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
|
||||
addPreferencesFromResource(R.xml.main);
|
||||
SharedPreferences prefs = getActivity().getSharedPreferences("main",
|
||||
Activity.MODE_PRIVATE);
|
||||
if (savedInstanceState == null && !prefs.getBoolean("first_warning_shown", false)) {
|
||||
showWarning();
|
||||
}
|
||||
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
Context context = getContext();
|
||||
|
||||
// Power efficient workqueue switch
|
||||
mPowerEfficientWorkqueueModeSwitch = (SwitchPreference) findPreference(Constants.KEY_POWER_EFFICIENT_WORKQUEUE);
|
||||
if (Utils.isFileWritable(Constants.NODE_POWER_EFFICIENT_WORKQUEUE)) {
|
||||
mPowerEfficientWorkqueueModeSwitch.setEnabled(true);
|
||||
mPowerEfficientWorkqueueModeSwitch.setChecked(sharedPrefs.getBoolean(Constants.KEY_POWER_EFFICIENT_WORKQUEUE, false));
|
||||
mPowerEfficientWorkqueueModeSwitch.setOnPreferenceChangeListener(this);
|
||||
} else {
|
||||
mPowerEfficientWorkqueueModeSwitch.setEnabled(false);
|
||||
}
|
||||
|
||||
// High brightness mode switches
|
||||
mHBMSwitch = (SwitchPreference) findPreference(Constants.KEY_HBM);
|
||||
mAutoHBMSwitch = (SwitchPreference) findPreference(Constants.KEY_AUTO_HBM);
|
||||
if (Utils.isFileWritable(Constants.NODE_HBM)) {
|
||||
mHBMSwitch.setEnabled(true);
|
||||
mHBMSwitch.setChecked(sharedPrefs.getBoolean(Constants.KEY_HBM, false));
|
||||
mHBMSwitch.setOnPreferenceChangeListener(this);
|
||||
mAutoHBMSwitch.setChecked(PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean(Constants.KEY_AUTO_HBM, false));
|
||||
mAutoHBMSwitch.setOnPreferenceChangeListener(this);
|
||||
} else {
|
||||
mHBMSwitch.setEnabled(false);
|
||||
mAutoHBMSwitch.setEnabled(false);
|
||||
}
|
||||
|
||||
// USB 2.0 fast charge switch
|
||||
mUSB2FastChargeSwitch = (SwitchPreference) findPreference(Constants.KEY_USB2_FAST_CHARGE);
|
||||
if (Utils.isFileWritable(Constants.NODE_USB2_FAST_CHARGE)) {
|
||||
mUSB2FastChargeSwitch.setEnabled(true);
|
||||
mUSB2FastChargeSwitch.setChecked(sharedPrefs.getBoolean(Constants.KEY_USB2_FAST_CHARGE, false));
|
||||
mUSB2FastChargeSwitch.setOnPreferenceChangeListener(this);
|
||||
} else {
|
||||
mUSB2FastChargeSwitch.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
// Power efficient workqueue switch
|
||||
if (preference == mPowerEfficientWorkqueueModeSwitch) {
|
||||
boolean enabled = (Boolean) newValue;
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
sharedPrefs.edit().putBoolean(Constants.KEY_POWER_EFFICIENT_WORKQUEUE, enabled).commit();
|
||||
Utils.writeValue(Constants.NODE_POWER_EFFICIENT_WORKQUEUE, enabled ? "1" : "0");
|
||||
return true;
|
||||
// High brightness mode switch
|
||||
} else if (preference == mHBMSwitch) {
|
||||
boolean enabled = (Boolean) newValue;
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
sharedPrefs.edit().putBoolean(Constants.KEY_HBM, enabled).commit();
|
||||
Utils.writeValue(Constants.NODE_HBM, enabled ? "1" : "0");
|
||||
Intent hbmServiceIntent = new Intent(this.getContext(), HBMService.class);
|
||||
if (enabled) {
|
||||
this.getContext().startService(hbmServiceIntent);
|
||||
} else {
|
||||
this.getContext().stopService(hbmServiceIntent);
|
||||
}
|
||||
return true;
|
||||
// Auto HBM switch
|
||||
} else if (preference == mAutoHBMSwitch) {
|
||||
Boolean enabled = (Boolean) newValue;
|
||||
SharedPreferences.Editor prefChange = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
|
||||
prefChange.putBoolean(Constants.KEY_AUTO_HBM, enabled).commit();
|
||||
AutoHBMUtils.enableAutoHBM(getContext());
|
||||
return true;
|
||||
// USB 2.0 fast charge switch
|
||||
} else if (preference == mUSB2FastChargeSwitch) {
|
||||
boolean enabled = (Boolean) newValue;
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getContext());
|
||||
sharedPrefs.edit().putBoolean(Constants.KEY_USB2_FAST_CHARGE, enabled).commit();
|
||||
Utils.writeValue(Constants.NODE_USB2_FAST_CHARGE, enabled ? "1" : "0");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAutoHBMEnabled(Context context) {
|
||||
return PreferenceManager.getDefaultSharedPreferences(context).getBoolean(Constants.KEY_AUTO_HBM, false);
|
||||
}
|
||||
|
||||
// Power efficient workqueue switch
|
||||
public static void restorePowerEfficientWorkqueueSetting(Context context) {
|
||||
if (Utils.isFileWritable(Constants.NODE_POWER_EFFICIENT_WORKQUEUE)) {
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean value = sharedPrefs.getBoolean(Constants.KEY_POWER_EFFICIENT_WORKQUEUE, false);
|
||||
Utils.writeValue(Constants.NODE_POWER_EFFICIENT_WORKQUEUE, value ? "1" : "0");
|
||||
}
|
||||
}
|
||||
|
||||
// High brightness mode switch
|
||||
public static void restoreHBMSetting(Context context) {
|
||||
if (Utils.isFileWritable(Constants.NODE_HBM)) {
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean value = sharedPrefs.getBoolean(Constants.KEY_HBM, false);
|
||||
Utils.writeValue(Constants.NODE_HBM, value ? "1" : "0");
|
||||
}
|
||||
}
|
||||
|
||||
// USB 2.0 fast charge switch
|
||||
public static void restoreUSB2FastChargeSetting(Context context) {
|
||||
if (Utils.isFileWritable(Constants.NODE_USB2_FAST_CHARGE)) {
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
boolean value = sharedPrefs.getBoolean(Constants.KEY_USB2_FAST_CHARGE, false);
|
||||
Utils.writeValue(Constants.NODE_USB2_FAST_CHARGE, value ? "1" : "0");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// First launch warning dialog
|
||||
public static class WarningDialogFragment extends DialogFragment {
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.pixel_parts_warning_title)
|
||||
.setMessage(R.string.pixel_parts_warning_text)
|
||||
.setNegativeButton(R.string.pixel_parts_dialog, (dialog, which) -> dialog.cancel())
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
getActivity().getSharedPreferences("main", Activity.MODE_PRIVATE)
|
||||
.edit()
|
||||
.putBoolean("first_warning_shown", true)
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
|
||||
private void showWarning() {
|
||||
WarningDialogFragment fragment = new WarningDialogFragment();
|
||||
fragment.show(getFragmentManager(), "warning_dialog");
|
||||
}
|
||||
}
|
||||
92
src/org/evolution/pixelparts/PixelPartsActivity.java
Normal file
92
src/org/evolution/pixelparts/PixelPartsActivity.java
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.Fragment;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import androidx.preference.PreferenceFragment;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
|
||||
import com.android.settingslib.widget.R;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
import com.plattysoft.leonids.ParticleSystem;
|
||||
|
||||
import org.evolution.pixelparts.utils.ShakeUtils;
|
||||
|
||||
public class PixelPartsActivity extends CollapsingToolbarBaseActivity
|
||||
implements ShakeUtils.OnShakeListener {
|
||||
|
||||
private static final String TAG = "PixelParts";
|
||||
|
||||
private ShakeUtils mShakeUtils;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
getFragmentManager().beginTransaction().replace(R.id.content_frame,
|
||||
new PixelParts(), TAG).commit();
|
||||
|
||||
mShakeUtils = new ShakeUtils(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mShakeUtils.bindShakeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
mShakeUtils.unBindShakeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
mShakeUtils.unBindShakeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onShake(double speed) {
|
||||
Random rand = new Random();
|
||||
int firstRandom = rand.nextInt(91-0);
|
||||
int secondRandom = rand.nextInt(181-90)+90;
|
||||
int thirdRandom = rand.nextInt(181-0);
|
||||
|
||||
Drawable easteregg = getResources().getDrawable(R.drawable.easteregg,null);
|
||||
int randomColor;
|
||||
randomColor = Color.rgb(
|
||||
Color.red(rand.nextInt(0xFFFFFF)),
|
||||
Color.green(rand.nextInt(0xFFFFFF)),
|
||||
Color.blue(rand.nextInt(0xFFFFFF)));
|
||||
easteregg.setTint(randomColor);
|
||||
|
||||
ParticleSystem ps = new ParticleSystem(this, 50, easteregg, 2000);
|
||||
ps.setScaleRange(0.7f,1.3f);
|
||||
ps.setSpeedRange(0.1f,0.25f);
|
||||
ps.setAcceleration(0.0001f,thirdRandom);
|
||||
ps.setRotationSpeedRange(firstRandom,secondRandom);
|
||||
ps.setFadeOut(300);
|
||||
ps.oneShot(this.findViewById(android.R.id.content),50);
|
||||
}
|
||||
}
|
||||
27
src/org/evolution/pixelparts/Startup.java
Normal file
27
src/org/evolution/pixelparts/Startup.java
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2022 crDroid Android Project
|
||||
* 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
public class Startup extends BroadcastReceiver {
|
||||
|
||||
private static final String TAG = Startup.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
final String action = intent.getAction();
|
||||
// PixelParts
|
||||
PixelParts.restorePowerEfficientWorkqueueSetting(context);
|
||||
PixelParts.restoreHBMSetting(context);
|
||||
PixelParts.restoreUSB2FastChargeSetting(context);
|
||||
}
|
||||
}
|
||||
23
src/org/evolution/pixelparts/misc/Constants.java
Normal file
23
src/org/evolution/pixelparts/misc/Constants.java
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.misc;
|
||||
|
||||
public class Constants {
|
||||
|
||||
// Power efficient workqueue switch
|
||||
public static final String KEY_POWER_EFFICIENT_WORKQUEUE = "power_efficient_workqueue";
|
||||
public static final String NODE_POWER_EFFICIENT_WORKQUEUE = "/sys/module/workqueue/parameters/power_efficient";
|
||||
|
||||
// High brightness mode switches
|
||||
public static final String KEY_HBM = "hbm";
|
||||
public static final String KEY_AUTO_HBM = "auto_hbm";
|
||||
public static final String KEY_AUTO_HBM_THRESHOLD = "auto_hbm_threshold";
|
||||
public static final String NODE_HBM = "/sys/class/backlight/panel0-backlight/hbm_mode";
|
||||
|
||||
// USB 2.0 fast charge switch
|
||||
public static final String KEY_USB2_FAST_CHARGE = "usb2_fast_charge";
|
||||
public static final String NODE_USB2_FAST_CHARGE = "/sys/kernel/fast_charge/force_fast_charge";
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The OmniROM Project
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.preferences;
|
||||
|
||||
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;
|
||||
|
||||
import org.evolution.pixelparts.misc.Constants;
|
||||
|
||||
public class AutoHBMThresholdPreference extends CustomSeekBarPreference {
|
||||
|
||||
private static int mMinVal = 2000;
|
||||
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(Constants.KEY_AUTO_HBM_THRESHOLD, "20000"));
|
||||
|
||||
setPersistent(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void changeValue(int newValue) {
|
||||
SharedPreferences.Editor prefChange = PreferenceManager.getDefaultSharedPreferences(getContext()).edit();
|
||||
prefChange.putString(Constants.KEY_AUTO_HBM_THRESHOLD, String.valueOf(newValue)).commit();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (C) 2016-2022 crDroid Android Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.preferences;
|
||||
|
||||
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.evolution.pixelparts.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);
|
||||
}
|
||||
}
|
||||
125
src/org/evolution/pixelparts/services/AutoHBMService.java
Normal file
125
src/org/evolution/pixelparts/services/AutoHBMService.java
Normal file
@@ -0,0 +1,125 @@
|
||||
package org.evolution.pixelparts.services;
|
||||
|
||||
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 org.evolution.pixelparts.misc.Constants;
|
||||
import org.evolution.pixelparts.utils.Utils;
|
||||
|
||||
public class AutoHBMService extends Service {
|
||||
|
||||
private static boolean mAutoHBMActive = false;
|
||||
|
||||
private SensorManager mSensorManager;
|
||||
Sensor mLightSensor;
|
||||
|
||||
private SharedPreferences mSharedPrefs;
|
||||
|
||||
public void activateLightSensorRead() {
|
||||
mSensorManager = (SensorManager) getApplicationContext().getSystemService(Context.SENSOR_SERVICE);
|
||||
mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
|
||||
mSensorManager.registerListener(mSensorEventListener, mLightSensor, SensorManager.SENSOR_DELAY_NORMAL);
|
||||
}
|
||||
|
||||
public void deactivateLightSensorRead() {
|
||||
mSensorManager.unregisterListener(mSensorEventListener);
|
||||
mAutoHBMActive = false;
|
||||
enableHBM(false);
|
||||
}
|
||||
|
||||
private void enableHBM(boolean enable) {
|
||||
if (enable) {
|
||||
Utils.writeValue(Constants.NODE_HBM, "1");
|
||||
} else {
|
||||
Utils.writeValue(Constants.NODE_HBM, "0");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isCurrentlyEnabled() {
|
||||
String fileValue = Utils.getFileValue(Constants.NODE_HBM, "0");
|
||||
return fileValue.equals("1") ? true : false;
|
||||
}
|
||||
|
||||
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 threshold = Float.parseFloat(mSharedPrefs.getString(Constants.KEY_AUTO_HBM_THRESHOLD, "20000"));
|
||||
if (lux > threshold) {
|
||||
if ((!mAutoHBMActive | !isCurrentlyEnabled()) && !keyguardShowing) {
|
||||
mAutoHBMActive = true;
|
||||
enableHBM(true);
|
||||
}
|
||||
}
|
||||
if (lux < threshold) {
|
||||
if (mAutoHBMActive) {
|
||||
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() {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@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;
|
||||
}
|
||||
}
|
||||
52
src/org/evolution/pixelparts/services/HBMService.java
Normal file
52
src/org/evolution/pixelparts/services/HBMService.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.services;
|
||||
|
||||
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.os.IBinder;
|
||||
import android.preference.PreferenceManager;
|
||||
|
||||
import org.evolution.pixelparts.misc.Constants;
|
||||
|
||||
public class HBMService extends Service {
|
||||
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
String action = intent.getAction();
|
||||
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||
SharedPreferences.Editor editor = preferences.edit();
|
||||
editor.putBoolean(Constants.KEY_HBM, false);
|
||||
editor.commit();
|
||||
stopSelf();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SCREEN_OFF);
|
||||
registerReceiver(mReceiver, intentFilter);
|
||||
return START_REDELIVER_INTENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
unregisterReceiver(mReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
}
|
||||
75
src/org/evolution/pixelparts/services/HBMTileService.java
Normal file
75
src/org/evolution/pixelparts/services/HBMTileService.java
Normal file
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.services;
|
||||
|
||||
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 org.evolution.pixelparts.misc.Constants;
|
||||
import org.evolution.pixelparts.utils.Utils;
|
||||
|
||||
public class HBMTileService extends TileService {
|
||||
|
||||
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(Constants.KEY_HBM, false).commit();
|
||||
updateTile(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void updateTile(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);
|
||||
updateTile(sharedPrefs.getBoolean(Constants.KEY_HBM, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopListening() {
|
||||
super.onStopListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
super.onClick();
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final boolean enabled = !(sharedPrefs.getBoolean(Constants.KEY_HBM, false));
|
||||
Utils.writeValue(Constants.NODE_HBM, enabled ? "1" : "0");
|
||||
sharedPrefs.edit().putBoolean(Constants.KEY_HBM, enabled).commit();
|
||||
updateTile(enabled);
|
||||
}
|
||||
}
|
||||
45
src/org/evolution/pixelparts/services/PEWQTileSerice.java
Normal file
45
src/org/evolution/pixelparts/services/PEWQTileSerice.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.services;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.service.quicksettings.Tile;
|
||||
import android.service.quicksettings.TileService;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.evolution.pixelparts.misc.Constants;
|
||||
import org.evolution.pixelparts.utils.Utils;
|
||||
|
||||
public class PEWQTileSerice extends TileService {
|
||||
|
||||
private void updateTile(boolean enabled) {
|
||||
final Tile tile = getQsTile();
|
||||
tile.setState(enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
|
||||
tile.updateTile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartListening() {
|
||||
super.onStartListening();
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
updateTile(sharedPrefs.getBoolean(Constants.KEY_POWER_EFFICIENT_WORKQUEUE, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopListening() {
|
||||
super.onStopListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
super.onClick();
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final boolean enabled = !(sharedPrefs.getBoolean(Constants.KEY_POWER_EFFICIENT_WORKQUEUE, false));
|
||||
Utils.writeValue(Constants.NODE_POWER_EFFICIENT_WORKQUEUE, enabled ? "1" : "0");
|
||||
sharedPrefs.edit().putBoolean(Constants.KEY_POWER_EFFICIENT_WORKQUEUE, enabled).commit();
|
||||
updateTile(enabled);
|
||||
}
|
||||
}
|
||||
45
src/org/evolution/pixelparts/services/USB2FCTileService.java
Normal file
45
src/org/evolution/pixelparts/services/USB2FCTileService.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Evolution X Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.services;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.service.quicksettings.Tile;
|
||||
import android.service.quicksettings.TileService;
|
||||
import androidx.preference.PreferenceManager;
|
||||
|
||||
import org.evolution.pixelparts.misc.Constants;
|
||||
import org.evolution.pixelparts.utils.Utils;
|
||||
|
||||
public class USB2FCTileService extends TileService {
|
||||
|
||||
private void updateTile(boolean enabled) {
|
||||
final Tile tile = getQsTile();
|
||||
tile.setState(enabled ? Tile.STATE_ACTIVE : Tile.STATE_INACTIVE);
|
||||
tile.updateTile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartListening() {
|
||||
super.onStartListening();
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
updateTile(sharedPrefs.getBoolean(Constants.KEY_USB2_FAST_CHARGE, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStopListening() {
|
||||
super.onStopListening();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick() {
|
||||
super.onClick();
|
||||
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final boolean enabled = !(sharedPrefs.getBoolean(Constants.KEY_USB2_FAST_CHARGE, false));
|
||||
Utils.writeValue(Constants.NODE_USB2_FAST_CHARGE, enabled ? "1" : "0");
|
||||
sharedPrefs.edit().putBoolean(Constants.KEY_USB2_FAST_CHARGE, enabled).commit();
|
||||
updateTile(enabled);
|
||||
}
|
||||
}
|
||||
357
src/org/evolution/pixelparts/uibench/JitterTestActivity.java
Normal file
357
src/org/evolution/pixelparts/uibench/JitterTestActivity.java
Normal file
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.uibench;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.ColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Message;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.FrameMetrics;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.Window.OnFrameMetricsAvailableListener;
|
||||
import android.view.animation.AnimationUtils;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.evolution.pixelparts.R;
|
||||
|
||||
public class JitterTestActivity extends Activity {
|
||||
private TextView mJitterReport;
|
||||
private TextView mUiFrameTimeReport;
|
||||
private TextView mRenderThreadTimeReport;
|
||||
private TextView mTotalFrameTimeReport;
|
||||
private TextView mMostlyTotalFrameTimeReport;
|
||||
private PointGraphView mGraph;
|
||||
|
||||
private static Handler sMetricsHandler;
|
||||
static {
|
||||
HandlerThread thread = new HandlerThread("frameMetricsListener");
|
||||
thread.start();
|
||||
sMetricsHandler = new Handler(thread.getLooper());
|
||||
}
|
||||
|
||||
private Handler mUpdateHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case R.id.jitter_mma:
|
||||
mJitterReport.setText((CharSequence) msg.obj);
|
||||
break;
|
||||
case R.id.totalish_mma:
|
||||
mMostlyTotalFrameTimeReport.setText((CharSequence) msg.obj);
|
||||
break;
|
||||
case R.id.ui_frametime_mma:
|
||||
mUiFrameTimeReport.setText((CharSequence) msg.obj);
|
||||
break;
|
||||
case R.id.rt_frametime_mma:
|
||||
mRenderThreadTimeReport.setText((CharSequence) msg.obj);
|
||||
break;
|
||||
case R.id.total_mma:
|
||||
mTotalFrameTimeReport.setText((CharSequence) msg.obj);
|
||||
break;
|
||||
case R.id.graph:
|
||||
mGraph.addJitterSample(msg.arg1, msg.arg2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.rendering_jitter);
|
||||
View content = findViewById(android.R.id.content);
|
||||
content.setBackground(new AnimatedBackgroundDrawable());
|
||||
content.setKeepScreenOn(true);
|
||||
mJitterReport = findViewById(R.id.jitter_mma);
|
||||
mMostlyTotalFrameTimeReport = findViewById(R.id.totalish_mma);
|
||||
mUiFrameTimeReport = findViewById(R.id.ui_frametime_mma);
|
||||
mRenderThreadTimeReport = findViewById(R.id.rt_frametime_mma);
|
||||
mTotalFrameTimeReport = findViewById(R.id.total_mma);
|
||||
mGraph = findViewById(R.id.graph);
|
||||
mJitterReport.setText("abcdefghijklmnopqrstuvwxyz");
|
||||
mMostlyTotalFrameTimeReport.setText("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
mUiFrameTimeReport.setText("0123456789");
|
||||
mRenderThreadTimeReport.setText(",.!()[]{};");
|
||||
getWindow().addOnFrameMetricsAvailableListener(mMetricsListener, sMetricsHandler);
|
||||
}
|
||||
|
||||
public static final class PointGraphView extends View {
|
||||
private static final float[] JITTER_LINES_MS = {
|
||||
.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 5.0f
|
||||
};
|
||||
private static final String[] JITTER_LINES_LABELS = makeLabels(JITTER_LINES_MS);
|
||||
private static final int[] JITTER_LINES_COLORS = new int[] {
|
||||
0xFF00E676, 0xFFFFF176, 0xFFFDD835, 0xFFFBC02D, 0xFFF9A825,
|
||||
0xFFF57F17, 0xFFDD2C00
|
||||
};
|
||||
private Paint mPaint = new Paint();
|
||||
private float[] mJitterYs = new float[JITTER_LINES_MS.length];
|
||||
private float mLabelWidth;
|
||||
private float mLabelHeight;
|
||||
private float mDensity;
|
||||
private float mGraphScale;
|
||||
private float mGraphMaxMs;
|
||||
|
||||
private float[] mJitterPoints;
|
||||
private float[] mJitterAvgPoints;
|
||||
|
||||
public PointGraphView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setWillNotDraw(false);
|
||||
mDensity = context.getResources().getDisplayMetrics().density;
|
||||
mPaint.setTextSize(dp(10));
|
||||
Rect textBounds = new Rect();
|
||||
mPaint.getTextBounds("8.8", 0, 3, textBounds);
|
||||
mLabelWidth = textBounds.width() + dp(2);
|
||||
mLabelHeight = textBounds.height();
|
||||
}
|
||||
|
||||
public void addJitterSample(int jitterUs, int jitterUsAvg) {
|
||||
for (int i = 1; i < mJitterPoints.length - 2; i += 2) {
|
||||
mJitterPoints[i] = mJitterPoints[i + 2];
|
||||
mJitterAvgPoints[i] = mJitterAvgPoints[i + 2];
|
||||
}
|
||||
mJitterPoints[mJitterPoints.length - 1] =
|
||||
getHeight() - mGraphScale * (jitterUs / 1000.0f);
|
||||
mJitterAvgPoints[mJitterAvgPoints.length - 1] =
|
||||
getHeight() - mGraphScale * (jitterUsAvg / 1000.0f);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private float dp(float dp) {
|
||||
return mDensity * dp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
canvas.drawColor(0x90000000);
|
||||
int h = getHeight();
|
||||
int w = getWidth();
|
||||
mPaint.setColor(Color.WHITE);
|
||||
mPaint.setStrokeWidth(dp(1));
|
||||
canvas.drawLine(mLabelWidth, 0, mLabelWidth, h, mPaint);
|
||||
for (int i = 0; i < JITTER_LINES_LABELS.length; i++) {
|
||||
canvas.drawText(JITTER_LINES_LABELS[i],
|
||||
0, (float) Math.floor(mJitterYs[i] + mLabelHeight * .5f), mPaint);
|
||||
}
|
||||
for (int i = 0; i < JITTER_LINES_LABELS.length; i++) {
|
||||
mPaint.setColor(JITTER_LINES_COLORS[i]);
|
||||
canvas.drawLine(mLabelWidth, mJitterYs[i], w, mJitterYs[i], mPaint);
|
||||
}
|
||||
mPaint.setStrokeWidth(dp(2));
|
||||
mPaint.setColor(Color.WHITE);
|
||||
canvas.drawPoints(mJitterPoints, mPaint);
|
||||
mPaint.setColor(0xFF2196F3);
|
||||
canvas.drawPoints(mJitterAvgPoints, mPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
|
||||
super.onSizeChanged(w, h, oldw, oldh);
|
||||
int graphWidth = (int) ((w - mLabelWidth - dp(1)) / mDensity);
|
||||
float[] oldJitterPoints = mJitterPoints;
|
||||
float[] oldJitterAvgPoints = mJitterAvgPoints;
|
||||
mJitterPoints = new float[graphWidth * 2];
|
||||
mJitterAvgPoints = new float[graphWidth * 2];
|
||||
for (int i = 0; i < mJitterPoints.length; i += 2) {
|
||||
mJitterPoints[i] = mLabelWidth + (i / 2 + 1) * mDensity;
|
||||
mJitterAvgPoints[i] = mJitterPoints[i];
|
||||
}
|
||||
if (oldJitterPoints != null) {
|
||||
int newIndexShift = Math.max(mJitterPoints.length - oldJitterPoints.length, 0);
|
||||
int oldIndexShift = oldJitterPoints.length - mJitterPoints.length;
|
||||
for (int i = 1 + newIndexShift; i < mJitterPoints.length; i += 2) {
|
||||
mJitterPoints[i] = oldJitterPoints[i + oldIndexShift];
|
||||
mJitterAvgPoints[i] = oldJitterAvgPoints[i + oldIndexShift];
|
||||
}
|
||||
}
|
||||
mGraphMaxMs = JITTER_LINES_MS[JITTER_LINES_MS.length - 1] + .5f;
|
||||
mGraphScale = (h / mGraphMaxMs);
|
||||
for (int i = 0; i < JITTER_LINES_MS.length; i++) {
|
||||
mJitterYs[i] = (float) Math.floor(h - mGraphScale * JITTER_LINES_MS[i]);
|
||||
}
|
||||
}
|
||||
|
||||
private static String[] makeLabels(float[] divisions) {
|
||||
String[] ret = new String[divisions.length];
|
||||
for (int i = 0; i < divisions.length; i++) {
|
||||
ret[i] = Float.toString(divisions[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
private final OnFrameMetricsAvailableListener mMetricsListener = new OnFrameMetricsAvailableListener() {
|
||||
private final static double WEIGHT = 40;
|
||||
private long mPreviousFrameTotal;
|
||||
private double mJitterMma;
|
||||
private double mUiFrametimeMma;
|
||||
private double mRtFrametimeMma;
|
||||
private double mTotalFrametimeMma;
|
||||
private double mMostlyTotalFrametimeMma;
|
||||
private boolean mNeedsFirstValues = true;
|
||||
|
||||
@Override
|
||||
public void onFrameMetricsAvailable(Window window, FrameMetrics frameMetrics,
|
||||
int dropCountSinceLastInvocation) {
|
||||
if (frameMetrics.getMetric(FrameMetrics.FIRST_DRAW_FRAME) == 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
long uiDuration = frameMetrics.getMetric(FrameMetrics.INPUT_HANDLING_DURATION)
|
||||
+ frameMetrics.getMetric(FrameMetrics.ANIMATION_DURATION)
|
||||
+ frameMetrics.getMetric(FrameMetrics.LAYOUT_MEASURE_DURATION)
|
||||
+ frameMetrics.getMetric(FrameMetrics.DRAW_DURATION);
|
||||
long rtDuration = frameMetrics.getMetric(FrameMetrics.SYNC_DURATION)
|
||||
+ frameMetrics.getMetric(FrameMetrics.COMMAND_ISSUE_DURATION);
|
||||
long totalDuration = frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION);
|
||||
long jitter = Math.abs(totalDuration - mPreviousFrameTotal);
|
||||
if (mNeedsFirstValues) {
|
||||
mJitterMma = 0;
|
||||
mUiFrametimeMma = uiDuration;
|
||||
mRtFrametimeMma = rtDuration;
|
||||
mTotalFrametimeMma = totalDuration;
|
||||
mMostlyTotalFrametimeMma = uiDuration + rtDuration;
|
||||
mNeedsFirstValues = false;
|
||||
} else {
|
||||
mJitterMma = add(mJitterMma, jitter);
|
||||
mUiFrametimeMma = add(mUiFrametimeMma, uiDuration);
|
||||
mRtFrametimeMma = add(mRtFrametimeMma, rtDuration);
|
||||
mTotalFrametimeMma = add(mTotalFrametimeMma, totalDuration);
|
||||
mMostlyTotalFrametimeMma = add(mMostlyTotalFrametimeMma, uiDuration + rtDuration);
|
||||
}
|
||||
mPreviousFrameTotal = totalDuration;
|
||||
mUpdateHandler.obtainMessage(R.id.jitter_mma,
|
||||
String.format("Jitter: %.3fms", toMs(mJitterMma))).sendToTarget();
|
||||
mUpdateHandler.obtainMessage(R.id.totalish_mma,
|
||||
String.format("CPU-total duration: %.3fms", toMs(mMostlyTotalFrametimeMma))).sendToTarget();
|
||||
mUpdateHandler.obtainMessage(R.id.ui_frametime_mma,
|
||||
String.format("UI duration: %.3fms", toMs(mUiFrametimeMma))).sendToTarget();
|
||||
mUpdateHandler.obtainMessage(R.id.rt_frametime_mma,
|
||||
String.format("RT duration: %.3fms", toMs(mRtFrametimeMma))).sendToTarget();
|
||||
mUpdateHandler.obtainMessage(R.id.total_mma,
|
||||
String.format("Total duration: %.3fms", toMs(mTotalFrametimeMma))).sendToTarget();
|
||||
mUpdateHandler.obtainMessage(R.id.graph, (int) (jitter / 1000),
|
||||
(int) (mJitterMma / 1000)).sendToTarget();
|
||||
}
|
||||
|
||||
double add(double previous, double today) {
|
||||
return (((WEIGHT - 1) * previous) + today) / WEIGHT;
|
||||
}
|
||||
|
||||
double toMs(double val) {
|
||||
return val / 1000000;
|
||||
}
|
||||
};
|
||||
|
||||
private static final class AnimatedBackgroundDrawable extends Drawable {
|
||||
private static final int FROM_COLOR = 0xFF18FFFF;
|
||||
private static final int TO_COLOR = 0xFF40C4FF;
|
||||
private static final int DURATION = 1400;
|
||||
|
||||
private final Paint mPaint;
|
||||
private boolean mReverse;
|
||||
private long mStartTime;
|
||||
private int mColor;
|
||||
|
||||
private boolean mReverseX;
|
||||
private boolean mReverseY;
|
||||
private float mX;
|
||||
private float mY;
|
||||
private float mRadius;
|
||||
private float mMoveStep = 10.0f;
|
||||
|
||||
public AnimatedBackgroundDrawable() {
|
||||
mPaint = new Paint();
|
||||
mPaint.setColor(0xFFFFFF00);
|
||||
mPaint.setAntiAlias(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
stepColor();
|
||||
canvas.drawColor(mColor);
|
||||
|
||||
mX += (mReverseX ? -mMoveStep : mMoveStep);
|
||||
mY += (mReverseY ? -mMoveStep : mMoveStep);
|
||||
clampXY();
|
||||
canvas.drawCircle(mX, mY, mRadius, mPaint);
|
||||
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
private void clampXY() {
|
||||
if (mX <= mRadius) {
|
||||
mReverseX = false;
|
||||
mX = mRadius;
|
||||
}
|
||||
if (mY <= mRadius) {
|
||||
mReverseY = false;
|
||||
mY = mRadius;
|
||||
}
|
||||
float maxX = getBounds().width() - mRadius;
|
||||
if (mX >= maxX) {
|
||||
mReverseX = true;
|
||||
mX = maxX;
|
||||
}
|
||||
float maxY = getBounds().height() - mRadius;
|
||||
if (mY >= maxY) {
|
||||
mReverseY = true;
|
||||
mY = maxY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBoundsChange(Rect bounds) {
|
||||
super.onBoundsChange(bounds);
|
||||
mMoveStep = Math.min(bounds.width(), bounds.height()) / 130.0f;
|
||||
mRadius = Math.min(bounds.width(), bounds.height()) / 20.0f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAlpha(int alpha) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColorFilter(ColorFilter colorFilter) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.OPAQUE;
|
||||
}
|
||||
|
||||
private void stepColor() {
|
||||
if (mStartTime == 0) {
|
||||
mStartTime = AnimationUtils.currentAnimationTimeMillis();
|
||||
}
|
||||
float frac = (AnimationUtils.currentAnimationTimeMillis() - mStartTime)
|
||||
/ (float) DURATION;
|
||||
if (frac > 1.0f) frac = 1.0f;
|
||||
int dest = mReverse ? FROM_COLOR : TO_COLOR;
|
||||
int src = mReverse ? TO_COLOR : FROM_COLOR;
|
||||
int r = (int) (Color.red(src) + (Color.red(dest) - Color.red(src)) * frac);
|
||||
int g = (int) (Color.green(src) + (Color.green(dest) - Color.green(src)) * frac);
|
||||
int b = (int) (Color.blue(src) + (Color.blue(dest) - Color.blue(src)) * frac);
|
||||
mColor = Color.rgb(r, g, b);
|
||||
if (frac == 1.0f) {
|
||||
mStartTime = 0;
|
||||
mReverse = !mReverse;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
src/org/evolution/pixelparts/utils/AutoHBMUtils.java
Normal file
33
src/org/evolution/pixelparts/utils/AutoHBMUtils.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package org.evolution.pixelparts.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.UserHandle;
|
||||
|
||||
import org.evolution.pixelparts.services.AutoHBMService;
|
||||
import org.evolution.pixelparts.PixelParts;
|
||||
|
||||
public class AutoHBMUtils {
|
||||
|
||||
private static boolean mAutoHBMEnabled = false;
|
||||
|
||||
private static void startAutoHBM(Context context) {
|
||||
context.startServiceAsUser(new Intent(context, AutoHBMService.class),
|
||||
UserHandle.CURRENT);
|
||||
mAutoHBMEnabled = true;
|
||||
}
|
||||
|
||||
private static void stopAutoHBM(Context context) {
|
||||
mAutoHBMEnabled = false;
|
||||
context.stopServiceAsUser(new Intent(context, AutoHBMService.class),
|
||||
UserHandle.CURRENT);
|
||||
}
|
||||
|
||||
public static void enableAutoHBM(Context context) {
|
||||
if (PixelParts.isAutoHBMEnabled(context) && !mAutoHBMEnabled) {
|
||||
startAutoHBM(context);
|
||||
} else if (!PixelParts.isAutoHBMEnabled(context) && mAutoHBMEnabled) {
|
||||
stopAutoHBM(context);
|
||||
}
|
||||
}
|
||||
}
|
||||
104
src/org/evolution/pixelparts/utils/ShakeUtils.kt
Normal file
104
src/org/evolution/pixelparts/utils/ShakeUtils.kt
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (C) 2021-2022 Miku UI
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.utils;
|
||||
|
||||
import android.content.Context
|
||||
import android.hardware.Sensor
|
||||
import android.hardware.SensorEvent
|
||||
import android.hardware.SensorEventListener
|
||||
import android.hardware.SensorManager
|
||||
import kotlin.math.sqrt
|
||||
|
||||
class ShakeUtils(context: Context) : SensorEventListener {
|
||||
private var mOnShakeListeners: ArrayList<OnShakeListener>? = null
|
||||
|
||||
// Last time we triggered shake
|
||||
private var mLastShakeTime = 0L
|
||||
private var mLastUpdateTime = 0L
|
||||
|
||||
// Last position we triggered shake
|
||||
private var mLastX = 0f
|
||||
private var mLastY = 0f
|
||||
private var mLastZ = 0f
|
||||
|
||||
interface OnShakeListener {
|
||||
fun onShake(speed: Double)
|
||||
}
|
||||
|
||||
fun bindShakeListener(listener: OnShakeListener?) {
|
||||
if (listener != null) {
|
||||
mOnShakeListeners?.add(listener)
|
||||
}
|
||||
}
|
||||
|
||||
fun unBindShakeListener(listener: OnShakeListener) {
|
||||
mOnShakeListeners?.remove(listener)
|
||||
}
|
||||
|
||||
override fun onSensorChanged(event: SensorEvent) {
|
||||
if (event == null) {
|
||||
return
|
||||
}
|
||||
val curUpdateTime = System.currentTimeMillis()
|
||||
// Times between two shakes
|
||||
val timeInterval = curUpdateTime - mLastUpdateTime
|
||||
if (timeInterval < SHAKE_INTERVAL_MILLISECOND) {
|
||||
return
|
||||
}
|
||||
if (event.values.size < 3) {
|
||||
return
|
||||
}
|
||||
mLastUpdateTime = curUpdateTime
|
||||
val x = event.values[0]
|
||||
val y = event.values[1]
|
||||
val z = event.values[2]
|
||||
val deltaX = x - mLastX
|
||||
val deltaY = y - mLastY
|
||||
val deltaZ = z - mLastZ
|
||||
mLastX = x
|
||||
mLastY = y
|
||||
mLastZ = z
|
||||
val speed =
|
||||
sqrt((deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ).toDouble()) * 1000.0 / timeInterval
|
||||
if (speed >= SPEED_SHAKE_MILLISECONDS) {
|
||||
startShake(speed)
|
||||
}
|
||||
}
|
||||
|
||||
private fun startShake(speed: Double) {
|
||||
val curShakeTime = System.currentTimeMillis()
|
||||
if (curShakeTime - mLastShakeTime < MIN_SHAKE_INTERVAL) {
|
||||
return
|
||||
}
|
||||
mLastShakeTime = curShakeTime
|
||||
mOnShakeListeners?.let {
|
||||
for (i in it.indices) {
|
||||
it[i].onShake(speed)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
|
||||
|
||||
companion object {
|
||||
|
||||
// Minimal time interval of position changes
|
||||
private const val MIN_SHAKE_INTERVAL = 1024
|
||||
|
||||
// Minimal shake speed
|
||||
private const val SPEED_SHAKE_MILLISECONDS = 400
|
||||
|
||||
// Minimal time interval between two shakes
|
||||
private const val SHAKE_INTERVAL_MILLISECOND = 55
|
||||
}
|
||||
|
||||
init {
|
||||
val mSensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
|
||||
val sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
|
||||
mSensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_UI)
|
||||
mOnShakeListeners = ArrayList()
|
||||
}
|
||||
}
|
||||
121
src/org/evolution/pixelparts/utils/Utils.java
Normal file
121
src/org/evolution/pixelparts/utils/Utils.java
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The CyanogenMod Project
|
||||
* 2018-2022 crDroid Android Project
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.evolution.pixelparts.utils;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileReader;
|
||||
|
||||
import org.evolution.pixelparts.R;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
public class Utils {
|
||||
|
||||
private static final String TAG = Utils.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* Reads the first line of text from the given file.
|
||||
* Reference {@link BufferedReader#readLine()} for clarification on what a line is
|
||||
*
|
||||
* @return the read line contents, or null on failure
|
||||
*/
|
||||
public static String readOneLine(String fileName) {
|
||||
String line = null;
|
||||
BufferedReader reader = null;
|
||||
|
||||
try {
|
||||
reader = new BufferedReader(new FileReader(fileName), 512);
|
||||
line = reader.readLine();
|
||||
} catch (FileNotFoundException e) {
|
||||
Log.w(TAG, "No such file " + fileName + " for reading", e);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Could not read from file " + fileName, e);
|
||||
} finally {
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignored, not much we can do anyway
|
||||
}
|
||||
}
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a string value to the specified file.
|
||||
* @param filename The filename
|
||||
* @param value The value
|
||||
*/
|
||||
public static void writeValue(String filename, String value) {
|
||||
if (filename == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(new File(filename));
|
||||
fos.write(value.getBytes());
|
||||
fos.flush();
|
||||
fos.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of the file with the given filename, or the specified default value if the file cannot be read.
|
||||
*
|
||||
* @param filename the name of the file to read
|
||||
* @param defValue the default value to return if the file cannot be read
|
||||
* @return the contents of the file as a String, or the default value if the file cannot be read
|
||||
*/
|
||||
public static String getFileValue(String filename, String defValue) {
|
||||
String fileValue = readOneLine(filename);
|
||||
if (fileValue != null) {
|
||||
return fileValue;
|
||||
}
|
||||
return defValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given file exists
|
||||
*
|
||||
* @return true if exists, false if not
|
||||
*/
|
||||
public static boolean fileExists(String fileName) {
|
||||
final File file = new File(fileName);
|
||||
return file.exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given file is readable
|
||||
*
|
||||
* @return true if readable, false if not
|
||||
*/
|
||||
public static boolean isFileReadable(String fileName) {
|
||||
final File file = new File(fileName);
|
||||
return file.exists() && file.canRead();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given file is writable
|
||||
*
|
||||
* @return true if writable, false if not
|
||||
*/
|
||||
public static boolean isFileWritable(String fileName) {
|
||||
final File file = new File(fileName);
|
||||
return file.exists() && file.canWrite();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user