17 Commits
bka ... main

Author SHA1 Message Date
yarpiin
8e1ff24b32 cupid: include Evolution build flags 2025-05-06 21:58:09 +01:00
yarpiin
b2924483f2 cupid: Change PRODUCT_MODEL to Xiaomi 12 2025-05-06 21:58:09 +01:00
yarpiin
9e896f49a1 cupid: add evolution.dependencies 2025-05-06 21:58:09 +01:00
ccfries
c10ce86331 cupid: Set VENDOR_SECURITY_PATCH To PLATFORM 2025-05-06 21:58:09 +01:00
Erfan Abdi
6012aee434 cupid: remove unwanted packages 2025-05-06 21:58:09 +01:00
Slawek
816071d898 cupid: parts: drop Thermal profiles 2025-05-06 21:58:09 +01:00
Chaohui Wang
e75c44bca2 cupid: parts: Migrate to CompoundButton.OnCheckedChangeListener
Switch and SwitchCompat are both CompoundButton.

Using CompoundButton in Java will helps migration in the future.

Bug: 306658427
Test: manual - check Settings pages
Test: m RunSettingsLibRoboTests
Change-Id: I85a70d4c504d8584030ea4a058f30d74206ab835
2025-05-06 21:58:09 +01:00
Peter Kalauskas
f43ee5182b cupid: parts: Enable use_resource_processor for all sysui deps
This will make the build faster

Test: m checkbuild
Bug: 295208392
Change-Id: I0c1bd901429bbe3bf81c1530e156735f8637a96e
2025-05-06 21:58:09 +01:00
Adithya R
f1a75fd99d cupid: parts: Fix thermal profile screen state handling 2025-05-06 21:58:09 +01:00
EmanuelCN
3fa6e860e2 cupid: parts: Checkout thermal profiles to xiaomi-sm8250 implementation 2025-05-06 21:58:09 +01:00
Arian
f8510853d4 cupid: parts: Import from xiaomi_sdm845-common
e261035d91/parts

Change-Id: I442f48780ca020f3e420ee4ccaf8ac07b05457cb
Signed-off-by: Anush02198 <anush.4376@gmail.com>
2025-05-06 21:58:09 +01:00
yarpiin
685d9bd793 cupid: set screen density to 380 2025-05-06 21:58:09 +01:00
gotenksIN
7f46a06cee cupid: overlay: Add PixelSetupWizardResTarget 2025-05-06 21:58:09 +01:00
Adithya R
6c856db12d cupid: Update display ids after display-drivers change
Recent kernel change in the display driver [1] caused a change in
display hardware port id which resulted in a change in display id.

[1]: 0a3ce41964

Change-Id: I58d3cb151ce3683643c6094758bee0a66bfa8cd5
2025-04-16 16:59:20 +02:00
Arian
58ffc1f96b cupid: Drop unused xiaomi mdss display config
Change-Id: I2e203ccb65533a7e75b34014235d51f3a5ddc689
2025-04-16 16:59:20 +02:00
Arian
03edd99f71 cupid: Update blobs and firmware from OS2.0.1.0.VLCMIXM
Change-Id: Ibfcb505e3416f42069c000cea33f3ec2433010dc
2025-04-16 16:59:20 +02:00
Arian
6ff3cd7f82 cupid: Enable ultrasound proximity sensor in audio hal
Change-Id: I7db1afd5ab2686e1f0c70e61ba1afe6fd3ba33ff
2025-04-16 16:59:20 +02:00
44 changed files with 2072 additions and 19 deletions

View File

@@ -20,7 +20,11 @@ TARGET_SYSTEM_PROP += $(DEVICE_PATH)/properties/system.prop
TARGET_VENDOR_PROP += $(DEVICE_PATH)/properties/vendor.prop
# Security patch level
VENDOR_SECURITY_PATCH := 2025-06-05
VENDOR_SECURITY_PATCH := $(PLATFORM_SECURITY_PATCH)
# Sepolicy
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += $(DEVICE_PATH)/sepolicy/private
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS += $(DEVICE_PATH)/sepolicy/public
# Screen density
TARGET_SCREEN_DENSITY := 380

View File

@@ -10,6 +10,10 @@ $(call inherit-product, device/xiaomi/sm8450-common/common.mk)
# Inherit from the proprietary version
$(call inherit-product, vendor/xiaomi/cupid/cupid-vendor.mk)
# Device-specific settings
PRODUCT_PACKAGES += \
XiaomiParts
# Audio
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/audio/mixer_paths_waipio_mtp.xml:$(TARGET_COPY_OUT_VENDOR)/etc/audio/sku_taro/mixer_paths_waipio_mtp.xml \
@@ -30,7 +34,7 @@ PRODUCT_PACKAGES += \
# Powershare
PRODUCT_PACKAGES += \
vendor.lineage.powershare-service.default
vendor.lineage.powershare@1.0-service.default
# Remove unwanted packages
PRODUCT_PACKAGES += \

View File

@@ -33,11 +33,9 @@ blob_fixups: blob_fixups_user_type = {
'vendor/etc/camera/pureShot_parameter.xml',
'vendor/etc/camera/pureView_parameter.xml',
): blob_fixup().regex_replace(r'=([0-9]+)>', r'="\1">'),
(
'vendor/lib64/hw/com.qti.chi.override.so',
'vendor/lib64/libcamxcommonutils.so',
'vendor/lib64/libmialgoengine.so',
): blob_fixup().add_needed('libprocessgroup_shim.so'),
'vendor/lib64/hw/com.qti.chi.override.so': blob_fixup().add_needed(
'libprocessgroup_shim.so'
),
'vendor/lib64/hw/fingerprint.goodix_fod.default.so': blob_fixup().binary_regex_replace(
b'/sys/class/touch/touch_dev/fod_press_status',
b'/sys/class/touch/touch_dev/fod_finger_state',
@@ -53,6 +51,9 @@ blob_fixups: blob_fixups_user_type = {
.clear_symbol_version('AHardwareBuffer_lockPlanes')
.clear_symbol_version('AHardwareBuffer_release')
.clear_symbol_version('AHardwareBuffer_unlock'),
'vendor/lib64/libcamxcommonutils.so': blob_fixup().add_needed(
'libprocessgroup_shim.so'
),
'vendor/lib64/libcamximageformatutils.so': blob_fixup().replace_needed(
'vendor.qti.hardware.display.config-V2-ndk_platform.so',
'vendor.qti.hardware.display.config-V2-ndk.so',
@@ -62,6 +63,9 @@ blob_fixups: blob_fixups_user_type = {
.clear_symbol_version('remote_handle64_invoke')
.clear_symbol_version('remote_handle64_open')
.clear_symbol_version('remote_register_buf_attr'),
'vendor/lib64/libmialgoengine.so': blob_fixup().add_needed(
'libprocessgroup_shim.so'
),
}
module = ExtractUtilsModule(

View File

@@ -1,6 +0,0 @@
[
{
"repository": "android_device_xiaomi_sm8450-common",
"target_path": "device/xiaomi/sm8450-common"
}
]

View File

@@ -17,8 +17,8 @@ PRODUCT_BRAND := Xiaomi
PRODUCT_MODEL := Xiaomi 12
PRODUCT_BUILD_PROP_OVERRIDES += \
BuildDesc="cupid_global-user 15 AQ3A.241006.001 OS2.0.3.0.VLCMIXM release-keys" \
BuildFingerprint=Xiaomi/cupid_global/cupid:15/AQ3A.241006.001/OS2.0.3.0.VLCMIXM:user/release-keys \
BuildDesc="cupid_global-user 15 AQ3A.241006.001 OS2.0.1.0.VLCMIXM release-keys" \
BuildFingerprint=Xiaomi/cupid_global/cupid:15/AQ3A.241006.001/OS2.0.1.0.VLCMIXM:user/release-keys \
DeviceProduct=cupid \
SystemName=cupid_global

25
parts/Android.bp Normal file
View File

@@ -0,0 +1,25 @@
//
// Copyright (C) 2017-2020 The LineageOS Project
//
// SPDX-License-Identifier: Apache-2.0
//
android_app {
name: "XiaomiParts",
srcs: ["src/**/*.java"],
certificate: "platform",
platform_apis: true,
system_ext_specific: true,
privileged: true,
static_libs: [
"org.lineageos.settings.resources",
],
optimize: {
proguard_flags_files: ["proguard.flags"],
},
}

93
parts/AndroidManifest.xml Normal file
View File

@@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015-2016 The CyanogenMod Project
2017-2018 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.lineageos.settings"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.GET_TASKS" />
<protected-broadcast android:name="com.android.systemui.doze.pulse" />
<uses-sdk
android:minSdkVersion="24"
android:targetSdkVersion="30"/>
<application
android:label="@string/device_settings_app_name"
android:persistent="true"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
android:theme="@style/Theme.SubSettingsBase">
<receiver android:name=".BootCompletedReceiver">
<intent-filter android:priority="1000">
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<activity
android:name=".doze.DozeSettingsActivity"
android:label="@string/ambient_display_title">
</activity>
<service android:name=".doze.DozeService"
android:permission="XiaomiDozeService">
</service>
<activity
android:name=".speaker.ClearSpeakerActivity"
android:label="@string/clear_speaker_title">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
</intent-filter>
<meta-data
android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.sound" />
<meta-data
android:name="com.android.settings.summary"
android:resource="@string/clear_speaker_summary" />
</activity>
<activity
android:name=".refreshrate.RefreshActivity"
android:label="@string/refresh_title"
android:exported="false">
<intent-filter>
<action android:name="com.android.settings.action.IA_SETTINGS" />
</intent-filter>
<meta-data
android:name="com.android.settings.category"
android:value="com.android.settings.category.ia.display" />
<meta-data
android:name="com.android.settings.summary"
android:resource="@string/refresh_summary" />
</activity>
<service
android:name=".refreshrate.RefreshService"
android:exported="true"
android:permission="RefreshService">
</service>
</application>
</manifest>

3
parts/proguard.flags Normal file
View File

@@ -0,0 +1,3 @@
-keep class org.lineageos.settings.doze.* {
*;
}

View File

@@ -0,0 +1,13 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="#000"
android:pathData="M20 4H4C2.9 4 2 4.9 2 6v12c0 1.1 0.9 2 2 2h16c1.1 0 2-0.9 2-2V6c0-1.1-0.9-2-2-2zm0 14H4V6h16v12z"/>
<path
android:fillColor="#000"
android:pathData="M8.29 15.71c-0.49-0.49-0.88-1.06-1.14-1.7c-0.26-0.64-0.4-1.32-0.4-2.01c0-1.35 0.52-2.69 1.53-3.72L7.05 7.05C5.68 8.41 5 10.21 5 12s0.68 3.59 2.06 4.94l1.23-1.23zM12 15.5c1.93 0 3.5-1.57 3.5-3.5S13.93 8.5 12 8.5S8.5 10.07 8.5 12s1.57 3.5 3.5 3.5zm0-5c0.83 0 1.5 0.67 1.5 1.5s-0.67 1.5-1.5 1.5s-1.5-0.67-1.5-1.5s0.67-1.5 1.5-1.5zm3.72 5.22l1.23 1.23C18.32 15.59 19 13.79 19 12s-0.68-3.59-2.06-4.94l-1.23 1.23c0.49 0.49 0.88 1.06 1.14 1.7c0.26 0.64 0.4 1.32 0.4 2.01c0 1.35-0.52 2.69-1.53 3.72z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M17,19V5H7V19H17M17,1A2,2 0 0,1 19,3V21A2,2 0 0,1 17,23H7C5.89,23 5,22.1 5,21V3C5,1.89 5.89,1 7,1H17M9,7H15V9H9V7M9,11H13V13H9V11Z" />
</vector>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M14.3,16L13.6,14H10.4L9.7,16H7.8L11,7H13L16.2,16H14.3M20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31L23.31,12L20,8.69M10.85,12.65H13.15L12,9L10.85,12.65Z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M12,8A4,4 0 0,0 8,12A4,4 0 0,0 12,16A4,4 0 0,0 16,12A4,4 0 0,0 12,8M12,18A6,6 0 0,1 6,12A6,6 0 0,1 12,6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31L23.31,12L20,8.69Z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M12,18V6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,15.31L23.31,12L20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31Z"/>
</vector>

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorAccent">
<path
android:fillColor="#ff000000"
android:pathData="M17 1.01L7 1C5.9 1 5 1.9 5 3v4h2V3h10v18H7v-4H5v4c0 1.1 0.9 2 2 2h10c1.1 0 2-0.9 2-2V3c0-1.1-0.9-1.99-2-1.99Z"/>
<path
android:fillColor="#ff000000"
android:pathData="M1 8v1.56h1.56v6.22H4.1V8H1Z"/>
<path
android:fillColor="#ff000000"
android:pathData="M4.89 8v1.56H8v1.55H6.44c-0.4 0-0.8 0.17-1.1 0.46-0.29 0.29-0.45 0.68-0.45 1.1v3.1h4.67v-1.55H6.44v-1.55H8c0.41 0 0.8-0.17 1.1-0.46 0.3-0.3 0.46-0.69 0.46-1.1V9.56c0-0.42-0.17-0.81-0.46-1.1C8.8 8.16 8.41 8 8 8H4.89Z"/>
<path
android:fillColor="#ff000000"
android:strokeColor="#ff000000"
android:strokeWidth="1"
android:pathData="M11.89 9.06h-0.5v0.5 4.66 0.5h0.5 1.55 0.5v-0.5-4.66-0.5h-0.5-1.55ZM11.14 8.8c0.2-0.2 0.47-0.31 0.75-0.31h1.55c0.28 0 0.55 0.11 0.75 0.3 0.2 0.2 0.31 0.48 0.31 0.76v4.66c0 0.28-0.11 0.55-0.3 0.75-0.2 0.2-0.48 0.3-0.76 0.3H11.9c-0.28 0-0.55-0.1-0.75-0.3-0.2-0.2-0.3-0.47-0.3-0.75V9.56c0-0.28 0.1-0.55 0.3-0.75Z"/>
</vector>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorAccent">
<path
android:fillColor="#ff000000"
android:pathData="M6.55 8c-0.4 0-0.8 0.16-1.1 0.46C5.17 8.75 5 9.14 5 9.56v4.66c0 0.4 0.16 0.8 0.46 1.1 0.29 0.29 0.68 0.45 1.1 0.45H8.1c0.41 0 0.8-0.16 1.1-0.46 0.29-0.29 0.45-0.68 0.45-1.1v-1.55c0-0.41-0.16-0.8-0.45-1.1-0.3-0.29-0.69-0.45-1.1-0.45H6.55V9.55h3.11V8h-3.1Zm0 4.66h1.56v1.56H6.55v-1.56Z"/>
<path
android:fillColor="#ff000000"
android:pathData="M12 8c-0.42 0-0.81 0.16-1.1 0.46-0.3 0.29-0.46 0.68-0.46 1.1v4.66c0 0.4 0.16 0.8 0.45 1.1 0.3 0.29 0.69 0.45 1.1 0.45h1.56c0.4 0 0.8-0.16 1.1-0.46 0.29-0.29 0.45-0.68 0.45-1.1V9.56c0-0.4-0.16-0.8-0.46-1.1C14.35 8.17 13.96 8 13.54 8H12Zm0 1.55h1.55v4.67h-1.56V9.55Z"/>
<path
android:fillColor="#ff000000"
android:pathData="M17 1.01L7 1C5.9 1 5 1.9 5 3v4h2V3h10v18H7v-4H5v4c0 1.1 0.9 2 2 2h10c1.1 0 2-0.9 2-2V3c0-1.1-0.9-1.99-2-1.99Z"/>
</vector>

View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorAccent">
<path
android:fillColor="#ff000000"
android:pathData="M17 3.01V15l2 2V3.01c0-1.1-0.9-1.99-2-1.99L7 1C6 0.99 5 1.99 5 2.99L7 5V3.01h10Zm4.2 18.19L19 19.01l-2-2-10-10-2-2-2.19-2.19L1.4 4.23 5 7.84v13.17c0 1.1 0.9 2 2 2h10c0.85 0 1.58-0.55 1.87-1.3l0.91 0.91 1.41-1.42ZM17 21.01H7L17 21v-0.99 1Zm-10 0V9.84l10 10.17V21L7 21.01Z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<!-- drawable/music_clef_bass.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
<path android:fillColor="#000" android:pathData="M18.5 5A1.5 1.5 0 1 1 17 6.5A1.5 1.5 0 0 1 18.5 5M18.5 11A1.5 1.5 0 1 1 17 12.5A1.5 1.5 0 0 1 18.5 11M10 4A5 5 0 0 0 5 9V10A2 2 0 1 0 7.18 8A3 3 0 0 1 10 6A4 4 0 0 1 14 10C14 13.59 11.77 16.19 7 18.2L7.76 20.04C13.31 17.72 16 14.43 16 10A6 6 0 0 0 10 4Z" />
</vector>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<androidx.recyclerview.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/refresh_rv_view"
android:layout_width="match_parent"
android:layout_height="wrap_content" />

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeight"
android:paddingBottom="4dp"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingTop="4dp">
<ImageView
android:id="@+id/app_icon"
android:layout_width="@android:dimen/app_icon_size"
android:layout_height="@android:dimen/app_icon_size"
android:layout_marginEnd="8dp"
android:contentDescription="@null"
android:scaleType="centerInside" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/app_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="2dp"
android:ellipsize="marquee"
android:singleLine="true"
android:textAlignment="viewStart"
android:textAppearance="@android:style/TextAppearance.Material.Medium"
android:textColor="?android:attr/textColorPrimary" />
<Spinner
android:id="@+id/app_mode"
android:layout_marginTop="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<ImageView
android:id="@+id/state"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="8dp"
android:scaleType="centerInside"
android:src="@drawable/ic_refresh_default" />
</LinearLayout>

Binary file not shown.

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2021 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<string-array name="doze_brightness_level">
<item>@string/doze_brightness_low</item>
<item>@string/doze_brightness_high</item>
<item>@string/doze_brightness_adaptive</item>
</string-array>
<string-array name="doze_brightness_level_mode">
<item>0</item>
<item>1</item>
<item>2</item>
</string-array>
</resources>

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2020 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<resources>
<!-- Per-app refresh rate -->
<string name="refresh_title">Per-app refresh rate</string>
<string name="refresh_summary">Set the maximum refresh rate for a specific application</string>
<string name="refresh_default">Default</string>
<string name="refresh_standard">60Hz</string>
<string name="refresh_extreme">120Hz</string>
<!-- Doze Strings -->
<string name="doze_brightness_low">Low brightness</string>
<string name="doze_brightness_high">High brightness</string>
<string name="doze_brightness_adaptive">Adaptive brightness</string>
<string name="doze_brightness_title">Doze brightness level</string>
<string name="doze_brightness_summary">Brightness level of doze pulse screen (% of max allowed brightness)</string>
<!-- Clear Speaker -->
<string name="clear_speaker_title">Clear speaker</string>
<string name="clear_speaker_summary">Play a 30-second audio to clear the speaker</string>
<string name="clear_speaker_description">Run this feature once or twice if you find that your speaker is lightly blocked by dust. Set media volume to maximum.\n\nIf the speaker is blocked heavily, run this feature 2-5 times while shaking your device with the speaker facing downwards.</string>
</resources>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/clear_speaker_title">
<SwitchPreference
android:key="clear_speaker_pref"
android:title="@string/clear_speaker_title"
android:icon="@drawable/ic_clear_speaker"
android:summary="@string/clear_speaker_summary"/>
<com.android.settingslib.widget.FooterPreference
android:key="footer_preference"
android:title="@string/clear_speaker_description"
android:selectable="false" />
</PreferenceScreen>

View File

@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The CyanogenMod Project
2018-2019 The LineageOS Project
Licensed under the Apache License, Version 2.0 (the "License"
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/ambient_display_title">
<com.android.settingslib.widget.MainSwitchPreference
android:defaultValue="false"
android:key="doze_enable"
android:title="@string/ambient_display_enable_title" />
<SwitchPreference
android:key="always_on_display"
android:disableDependentsState="true"
android:icon="@drawable/ic_doze_aod"
android:title="@string/ambient_display_always_on_title"
android:summary="@string/ambient_display_always_on_summary"
android:persistent="false" />
<ListPreference
android:key="doze_brightness"
android:defaultValue="2"
android:title="@string/doze_brightness_title"
android:summary="@string/doze_brightness_summary"
android:entries="@array/doze_brightness_level"
android:entryValues="@array/doze_brightness_level_mode" />
</PreferenceScreen>

View File

@@ -0,0 +1,39 @@
/*
* Copyright (C) 2015 The CyanogenMod Project
* 2017-2019 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import org.lineageos.settings.doze.DozeUtils;
import org.lineageos.settings.refreshrate.RefreshUtils;
public class BootCompletedReceiver extends BroadcastReceiver {
private static final boolean DEBUG = false;
private static final String TAG = "XiaomiParts";
@Override
public void onReceive(final Context context, Intent intent) {
if (DEBUG)
Log.d(TAG, "Received boot completed intent");
DozeUtils.onBootCompleted(context);
RefreshUtils.startService(context);
}
}

View File

@@ -0,0 +1,80 @@
/*
* Copyright (C) 2021 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.doze;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class AodSensor implements SensorEventListener {
private static final boolean DEBUG = false;
private static final String TAG = "AodSensor";
private SensorManager mSensorManager;
private Sensor mSensor;
private Context mContext;
private ExecutorService mExecutorService;
public AodSensor(Context context) {
mContext = context;
mSensorManager = mContext.getSystemService(SensorManager.class);
mSensor = DozeUtils.getSensor(mSensorManager, "xiaomi.sensor.aod");
mExecutorService = Executors.newSingleThreadExecutor();
}
private Future<?> submit(Runnable runnable) { return mExecutorService.submit(runnable); }
@Override
public void onSensorChanged(SensorEvent event) {
if (DEBUG) {
Log.d(TAG, "Got sensor event: " + event.values[0]);
}
if (event.values[0] == 3 || event.values[0] == 5) {
DozeUtils.setDozeMode(DozeUtils.DOZE_MODE_LBM);
} else if (event.values[0] == 4) {
DozeUtils.setDozeMode(DozeUtils.DOZE_MODE_HBM);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
/* Empty */
}
protected void enable() {
if (DEBUG) {
Log.d(TAG, "Enabling");
}
submit(() -> {
mSensorManager.registerListener(this, mSensor, SensorManager.SENSOR_DELAY_NORMAL);
});
}
protected void disable() {
if (DEBUG) {
Log.d(TAG, "Disabling");
}
submit(() -> { mSensorManager.unregisterListener(this, mSensor); });
}
}

View File

@@ -0,0 +1,92 @@
/*
* Copyright (C) 2015 The CyanogenMod Project
* 2017-2018 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.doze;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.IBinder;
import android.util.Log;
public class DozeService extends Service {
private static final String TAG = "DozeService";
private static final boolean DEBUG = false;
private AodSensor mAodSensor;
@Override
public void onCreate() {
if (DEBUG)
Log.d(TAG, "Creating service");
mAodSensor = new AodSensor(this);
IntentFilter screenStateFilter = new IntentFilter();
screenStateFilter.addAction(Intent.ACTION_SCREEN_ON);
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
registerReceiver(mScreenStateReceiver, screenStateFilter);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (DEBUG)
Log.d(TAG, "Starting service");
return START_STICKY;
}
@Override
public void onDestroy() {
if (DEBUG)
Log.d(TAG, "Destroying service");
super.onDestroy();
this.unregisterReceiver(mScreenStateReceiver);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void onDisplayOn() {
if (DEBUG)
Log.d(TAG, "Display on");
if (DozeUtils.isDozeAutoBrightnessEnabled(this)) {
mAodSensor.disable();
}
}
private void onDisplayOff() {
if (DEBUG)
Log.d(TAG, "Display off");
if (DozeUtils.isDozeAutoBrightnessEnabled(this)) {
mAodSensor.enable();
}
}
private BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
onDisplayOn();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
onDisplayOff();
}
}
};
}

View File

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

View File

@@ -0,0 +1,156 @@
/*
* Copyright (C) 2015 The CyanogenMod Project
* 2017-2019 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.doze;
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.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceChangeListener;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragment;
import androidx.preference.SwitchPreference;
import com.android.settingslib.widget.MainSwitchPreference;
import org.lineageos.settings.R;
import org.lineageos.settings.utils.FileUtils;
public class DozeSettingsFragment extends PreferenceFragment
implements OnPreferenceChangeListener, OnCheckedChangeListener {
private MainSwitchPreference mSwitchBar;
private SwitchPreference mAlwaysOnDisplayPreference;
private ListPreference mDozeBrightnessPreference;
private Handler mHandler = new Handler();
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.doze_settings);
SharedPreferences prefs =
getActivity().getSharedPreferences("doze_settings", Activity.MODE_PRIVATE);
if (savedInstanceState == null && !prefs.getBoolean("first_help_shown", false)) {
showHelp();
}
boolean dozeEnabled = DozeUtils.isDozeEnabled(getActivity());
mSwitchBar = (MainSwitchPreference) findPreference(DozeUtils.DOZE_ENABLE);
mSwitchBar.addOnSwitchChangeListener(this);
mSwitchBar.setChecked(dozeEnabled);
mAlwaysOnDisplayPreference = (SwitchPreference) findPreference(DozeUtils.ALWAYS_ON_DISPLAY);
mAlwaysOnDisplayPreference.setEnabled(dozeEnabled);
mAlwaysOnDisplayPreference.setChecked(DozeUtils.isAlwaysOnEnabled(getActivity()));
mAlwaysOnDisplayPreference.setOnPreferenceChangeListener(this);
mDozeBrightnessPreference = (ListPreference) findPreference(DozeUtils.DOZE_BRIGHTNESS_KEY);
mDozeBrightnessPreference.setEnabled(
dozeEnabled && DozeUtils.isAlwaysOnEnabled(getActivity()));
mDozeBrightnessPreference.setOnPreferenceChangeListener(this);
// Hide AOD and doze brightness if not supported and set all its dependents otherwise
if (!DozeUtils.alwaysOnDisplayAvailable(getActivity())) {
getPreferenceScreen().removePreference(mAlwaysOnDisplayPreference);
getPreferenceScreen().removePreference(mDozeBrightnessPreference);
} else {
if (!FileUtils.isFileWritable(DozeUtils.DOZE_MODE_PATH)) {
getPreferenceScreen().removePreference(mDozeBrightnessPreference);
} else {
DozeUtils.updateDozeBrightnessIcon(getContext(), mDozeBrightnessPreference);
}
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (DozeUtils.ALWAYS_ON_DISPLAY.equals(preference.getKey())) {
DozeUtils.enableAlwaysOn(getActivity(), (Boolean) newValue);
if (!(Boolean) newValue) {
mDozeBrightnessPreference.setValue(DozeUtils.DOZE_BRIGHTNESS_LBM);
DozeUtils.setDozeMode(DozeUtils.DOZE_BRIGHTNESS_LBM);
}
mDozeBrightnessPreference.setEnabled((Boolean) newValue);
} else if (DozeUtils.DOZE_BRIGHTNESS_KEY.equals(preference.getKey())) {
if (!DozeUtils.DOZE_BRIGHTNESS_AUTO.equals((String) newValue)) {
DozeUtils.setDozeMode((String) newValue);
}
}
mHandler.post(() -> {
DozeUtils.checkDozeService(getActivity());
DozeUtils.updateDozeBrightnessIcon(getContext(), mDozeBrightnessPreference);
});
return true;
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
DozeUtils.enableDoze(getActivity(), isChecked);
DozeUtils.checkDozeService(getActivity());
mSwitchBar.setChecked(isChecked);
if (!isChecked) {
DozeUtils.enableAlwaysOn(getActivity(), false);
mAlwaysOnDisplayPreference.setChecked(false);
mDozeBrightnessPreference.setValue(DozeUtils.DOZE_BRIGHTNESS_LBM);
DozeUtils.updateDozeBrightnessIcon(getContext(), mDozeBrightnessPreference);
}
mAlwaysOnDisplayPreference.setEnabled(isChecked);
mDozeBrightnessPreference.setEnabled(
isChecked && DozeUtils.isAlwaysOnEnabled(getActivity()));
}
public static class HelpDialogFragment extends DialogFragment {
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.doze_settings_help_title)
.setMessage(R.string.doze_settings_help_text)
.setNegativeButton(R.string.dialog_ok, (dialog, which) -> dialog.cancel())
.create();
}
@Override
public void onCancel(DialogInterface dialog) {
getActivity()
.getSharedPreferences("doze_settings", Activity.MODE_PRIVATE)
.edit()
.putBoolean("first_help_shown", true)
.commit();
}
}
private void showHelp() {
HelpDialogFragment fragment = new HelpDialogFragment();
fragment.show(getFragmentManager(), "help_dialog");
}
}

View File

@@ -0,0 +1,155 @@
/*
* Copyright (C) 2015 The CyanogenMod Project
* 2017-2019 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.doze;
import static android.provider.Settings.Secure.DOZE_ALWAYS_ON;
import static android.provider.Settings.Secure.DOZE_ENABLED;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Log;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceManager;
import org.lineageos.settings.R;
import org.lineageos.settings.utils.FileUtils;
public final class DozeUtils {
private static final String TAG = "DozeUtils";
private static final boolean DEBUG = false;
private static final String DOZE_INTENT = "com.android.systemui.doze.pulse";
protected static final String DOZE_ENABLE = "doze_enable";
protected static final String ALWAYS_ON_DISPLAY = "always_on_display";
protected static final String DOZE_BRIGHTNESS_KEY = "doze_brightness";
protected static final String DOZE_MODE_PATH =
"/sys/devices/platform/soc/soc:qcom,dsi-display-primary/doze_mode";
protected static final String DOZE_MODE_HBM = "1";
protected static final String DOZE_MODE_LBM = "0";
protected static final String DOZE_BRIGHTNESS_LBM = "0";
protected static final String DOZE_BRIGHTNESS_HBM = "1";
protected static final String DOZE_BRIGHTNESS_AUTO = "2";
public static void onBootCompleted(Context context) {
checkDozeService(context);
restoreDozeModes(context);
}
public static void startService(Context context) {
if (DEBUG)
Log.d(TAG, "Starting service");
context.startServiceAsUser(new Intent(context, DozeService.class), UserHandle.CURRENT);
}
protected static void stopService(Context context) {
if (DEBUG)
Log.d(TAG, "Stopping service");
context.stopServiceAsUser(new Intent(context, DozeService.class), UserHandle.CURRENT);
}
public static void checkDozeService(Context context) {
if (isDozeEnabled(context)
&& (isAlwaysOnEnabled(context) || sensorsEnabled(context))) {
startService(context);
} else {
stopService(context);
}
}
private static void restoreDozeModes(Context context) {
if (isAlwaysOnEnabled(context) && !isDozeAutoBrightnessEnabled(context)) {
setDozeMode(PreferenceManager.getDefaultSharedPreferences(context).getString(
DOZE_BRIGHTNESS_KEY, String.valueOf(DOZE_BRIGHTNESS_LBM)));
}
}
protected static boolean enableDoze(Context context, boolean enable) {
return Settings.Secure.putInt(context.getContentResolver(), DOZE_ENABLED, enable ? 1 : 0);
}
public static boolean isDozeEnabled(Context context) {
return Settings.Secure.getInt(context.getContentResolver(), DOZE_ENABLED, 1) != 0;
}
protected static boolean enableAlwaysOn(Context context, boolean enable) {
return Settings.Secure.putIntForUser(context.getContentResolver(), DOZE_ALWAYS_ON,
enable ? 1 : 0, UserHandle.USER_CURRENT);
}
protected static boolean isAlwaysOnEnabled(Context context) {
final boolean enabledByDefault = context.getResources().getBoolean(
com.android.internal.R.bool.config_dozeAlwaysOnEnabled);
return Settings.Secure.getIntForUser(context.getContentResolver(), DOZE_ALWAYS_ON,
alwaysOnDisplayAvailable(context) && enabledByDefault ? 1 : 0,
UserHandle.USER_CURRENT)
!= 0;
}
protected static boolean alwaysOnDisplayAvailable(Context context) {
return new AmbientDisplayConfiguration(context).alwaysOnAvailable();
}
protected static boolean setDozeMode(String value) {
return FileUtils.writeLine(DOZE_MODE_PATH, value);
}
protected static boolean isDozeAutoBrightnessEnabled(Context context) {
return PreferenceManager.getDefaultSharedPreferences(context)
.getString(DOZE_BRIGHTNESS_KEY, DOZE_BRIGHTNESS_LBM)
.equals(DOZE_BRIGHTNESS_AUTO);
}
public static boolean sensorsEnabled(Context context) {
return isDozeAutoBrightnessEnabled(context);
}
protected static Sensor getSensor(SensorManager sm, String type) {
for (Sensor sensor : sm.getSensorList(Sensor.TYPE_ALL)) {
if (type.equals(sensor.getStringType())) {
return sensor;
}
}
return null;
}
protected static void updateDozeBrightnessIcon(Context context, ListPreference preference) {
switch (PreferenceManager.getDefaultSharedPreferences(context).getString(
DOZE_BRIGHTNESS_KEY, DOZE_BRIGHTNESS_LBM)) {
case DozeUtils.DOZE_BRIGHTNESS_LBM:
preference.setIcon(R.drawable.ic_doze_brightness_low);
break;
case DozeUtils.DOZE_BRIGHTNESS_HBM:
preference.setIcon(R.drawable.ic_doze_brightness_high);
break;
case DozeUtils.DOZE_BRIGHTNESS_AUTO:
preference.setIcon(R.drawable.ic_doze_brightness_auto);
break;
}
}
}

View File

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

View File

@@ -0,0 +1,102 @@
/*
* Copyright (C) 2020 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.refreshrate;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.ActivityTaskManager.RootTaskInfo;
import android.app.IActivityTaskManager;
import android.app.TaskStackListener;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;
import android.os.RemoteException;
public class RefreshService extends Service {
private static final String TAG = "RefreshService";
private static final boolean DEBUG = true;
private String mPreviousApp;
private RefreshUtils mRefreshUtils;
private IActivityTaskManager mActivityTaskManager;
private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
mPreviousApp = "";
}
};
@Override
public void onCreate() {
if (DEBUG) Log.d(TAG, "Creating service");
try {
mActivityTaskManager = ActivityTaskManager.getService();
mActivityTaskManager.registerTaskStackListener(mTaskListener);
} catch (RemoteException e) {
// Do nothing
}
mRefreshUtils = new RefreshUtils(this);
registerReceiver();
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (DEBUG) Log.d(TAG, "Starting service");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void registerReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
filter.addAction(Intent.ACTION_SCREEN_ON);
this.registerReceiver(mIntentReceiver, filter);
}
private final TaskStackListener mTaskListener = new TaskStackListener() {
@Override
public void onTaskStackChanged() {
try {
final RootTaskInfo info = mActivityTaskManager.getFocusedRootTaskInfo();
if (info == null || info.topActivity == null) {
return;
}
String foregroundApp = info.topActivity.getPackageName();
if (!mRefreshUtils.isAppInList) {
mRefreshUtils.getOldRate();
}
if (!foregroundApp.equals(mPreviousApp)) {
mRefreshUtils.setRefreshRate(foregroundApp);
mPreviousApp = foregroundApp;
}
} catch (Exception e) {}
}
};
}

View File

@@ -0,0 +1,419 @@
/**
* Copyright (C) 2020 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.refreshrate;
import android.annotation.Nullable;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.SectionIndexer;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.preference.PreferenceFragment;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.android.settingslib.applications.ApplicationsState;
import org.lineageos.settings.R;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class RefreshSettingsFragment extends PreferenceFragment
implements ApplicationsState.Callbacks {
private AllPackagesAdapter mAllPackagesAdapter;
private ApplicationsState mApplicationsState;
private ApplicationsState.Session mSession;
private ActivityFilter mActivityFilter;
private Map<String, ApplicationsState.AppEntry> mEntryMap =
new HashMap<String, ApplicationsState.AppEntry>();
private RefreshUtils mRefreshUtils;
private RecyclerView mAppsRecyclerView;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mApplicationsState = ApplicationsState.getInstance(getActivity().getApplication());
mSession = mApplicationsState.newSession(this);
mSession.onResume();
mActivityFilter = new ActivityFilter(getActivity().getPackageManager());
mAllPackagesAdapter = new AllPackagesAdapter(getActivity());
mRefreshUtils = new RefreshUtils(getActivity());
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.refresh_layout, container, false);
}
@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mAppsRecyclerView = view.findViewById(R.id.refresh_rv_view);
mAppsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mAppsRecyclerView.setAdapter(mAllPackagesAdapter);
}
@Override
public void onResume() {
super.onResume();
getActivity().setTitle(getResources().getString(R.string.refresh_title));
rebuild();
}
@Override
public void onDestroy() {
super.onDestroy();
mSession.onPause();
mSession.onDestroy();
}
@Override
public void onPackageListChanged() {
mActivityFilter.updateLauncherInfoList();
rebuild();
}
@Override
public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> entries) {
if (entries != null) {
handleAppEntries(entries);
mAllPackagesAdapter.notifyDataSetChanged();
}
}
@Override
public void onLoadEntriesCompleted() {
rebuild();
}
@Override
public void onAllSizesComputed() {
}
@Override
public void onLauncherInfoChanged() {
}
@Override
public void onPackageIconChanged() {
}
@Override
public void onPackageSizeChanged(String packageName) {
}
@Override
public void onRunningStateChanged(boolean running) {
}
private void handleAppEntries(List<ApplicationsState.AppEntry> entries) {
final ArrayList<String> sections = new ArrayList<String>();
final ArrayList<Integer> positions = new ArrayList<Integer>();
final PackageManager pm = getActivity().getPackageManager();
String lastSectionIndex = null;
int offset = 0;
for (int i = 0; i < entries.size(); i++) {
final ApplicationInfo info = entries.get(i).info;
final String label = (String) info.loadLabel(pm);
final String sectionIndex;
if (!info.enabled) {
sectionIndex = "--"; // XXX
} else if (TextUtils.isEmpty(label)) {
sectionIndex = "";
} else {
sectionIndex = label.substring(0, 1).toUpperCase();
}
if (lastSectionIndex == null ||
!TextUtils.equals(sectionIndex, lastSectionIndex)) {
sections.add(sectionIndex);
positions.add(offset);
lastSectionIndex = sectionIndex;
}
offset++;
}
mAllPackagesAdapter.setEntries(entries, sections, positions);
mEntryMap.clear();
for (ApplicationsState.AppEntry e : entries) {
mEntryMap.put(e.info.packageName, e);
}
}
private void rebuild() {
mSession.rebuild(mActivityFilter, ApplicationsState.ALPHA_COMPARATOR);
}
private int getStateDrawable(int state) {
switch (state) {
case RefreshUtils.STATE_STANDARD:
return R.drawable.ic_refresh_60;
case RefreshUtils.STATE_EXTREME:
return R.drawable.ic_refresh_120;
case RefreshUtils.STATE_DEFAULT:
default:
return R.drawable.ic_refresh_default;
}
}
private class ViewHolder extends RecyclerView.ViewHolder {
private TextView title;
private Spinner mode;
private ImageView icon;
private View rootView;
private ImageView stateIcon;
private ViewHolder(View view) {
super(view);
this.title = view.findViewById(R.id.app_name);
this.mode = view.findViewById(R.id.app_mode);
this.icon = view.findViewById(R.id.app_icon);
this.stateIcon = view.findViewById(R.id.state);
this.rootView = view;
view.setTag(this);
}
}
private class ModeAdapter extends BaseAdapter {
private final LayoutInflater inflater;
private final int[] items = {
R.string.refresh_default,
R.string.refresh_standard,
R.string.refresh_extreme
};
private ModeAdapter(Context context) {
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return items.length;
}
@Override
public Object getItem(int position) {
return items[position];
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView view;
if (convertView != null) {
view = (TextView) convertView;
} else {
view = (TextView) inflater.inflate(android.R.layout.simple_spinner_dropdown_item,
parent, false);
}
view.setText(items[position]);
view.setTextSize(14f);
return view;
}
}
private class AllPackagesAdapter extends RecyclerView.Adapter<ViewHolder>
implements AdapterView.OnItemSelectedListener, SectionIndexer {
private List<ApplicationsState.AppEntry> mEntries = new ArrayList<>();
private String[] mSections;
private int[] mPositions;
public AllPackagesAdapter(Context context) {
mActivityFilter = new ActivityFilter(context.getPackageManager());
}
@Override
public int getItemCount() {
return mEntries.size();
}
@Override
public long getItemId(int position) {
return mEntries.get(position).id;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(LayoutInflater.from(parent.getContext())
.inflate(R.layout.refresh_list_item, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Context context = holder.itemView.getContext();
ApplicationsState.AppEntry entry = mEntries.get(position);
if (entry == null) {
return;
}
holder.mode.setAdapter(new ModeAdapter(context));
holder.mode.setOnItemSelectedListener(this);
holder.title.setText(entry.label);
holder.title.setOnClickListener(v -> holder.mode.performClick());
mApplicationsState.ensureIcon(entry);
holder.icon.setImageDrawable(entry.icon);
int packageState = mRefreshUtils.getStateForPackage(entry.info.packageName);
holder.mode.setSelection(packageState, false);
holder.mode.setTag(entry);
holder.stateIcon.setImageResource(getStateDrawable(packageState));
}
private void setEntries(List<ApplicationsState.AppEntry> entries,
List<String> sections, List<Integer> positions) {
mEntries = entries;
mSections = sections.toArray(new String[sections.size()]);
mPositions = new int[positions.size()];
for (int i = 0; i < positions.size(); i++) {
mPositions[i] = positions.get(i);
}
notifyDataSetChanged();
}
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
final ApplicationsState.AppEntry entry = (ApplicationsState.AppEntry) parent.getTag();
int currentState = mRefreshUtils.getStateForPackage(entry.info.packageName);
if (currentState != position) {
mRefreshUtils.writePackage(entry.info.packageName, position);
notifyDataSetChanged();
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
@Override
public int getPositionForSection(int section) {
if (section < 0 || section >= mSections.length) {
return -1;
}
return mPositions[section];
}
@Override
public int getSectionForPosition(int position) {
if (position < 0 || position >= getItemCount()) {
return -1;
}
final int index = Arrays.binarySearch(mPositions, position);
/*
* Consider this example: section positions are 0, 3, 5; the supplied
* position is 4. The section corresponding to position 4 starts at
* position 3, so the expected return value is 1. Binary search will not
* find 4 in the array and thus will return -insertPosition-1, i.e. -3.
* To get from that number to the expected value of 1 we need to negate
* and subtract 2.
*/
return index >= 0 ? index : -index - 2;
}
@Override
public Object[] getSections() {
return mSections;
}
}
private class ActivityFilter implements ApplicationsState.AppFilter {
private final PackageManager mPackageManager;
private final List<String> mLauncherResolveInfoList = new ArrayList<String>();
private ActivityFilter(PackageManager packageManager) {
this.mPackageManager = packageManager;
updateLauncherInfoList();
}
public void updateLauncherInfoList() {
Intent i = new Intent(Intent.ACTION_MAIN);
i.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveInfoList = mPackageManager.queryIntentActivities(i, 0);
synchronized (mLauncherResolveInfoList) {
mLauncherResolveInfoList.clear();
for (ResolveInfo ri : resolveInfoList) {
mLauncherResolveInfoList.add(ri.activityInfo.packageName);
}
}
}
@Override
public void init() {
}
@Override
public boolean filterApp(ApplicationsState.AppEntry entry) {
boolean show = !mAllPackagesAdapter.mEntries.contains(entry.info.packageName);
if (show) {
synchronized (mLauncherResolveInfoList) {
show = mLauncherResolveInfoList.contains(entry.info.packageName);
}
}
return show;
}
}
}

View File

@@ -0,0 +1,141 @@
/*
* Copyright (C) 2020 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.refreshrate;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.UserHandle;
import android.view.Display;
import android.provider.Settings;
import androidx.preference.PreferenceManager;
public final class RefreshUtils {
private static final String REFRESH_CONTROL = "refresh_control";
private static float defaultMaxRate;
private static float defaultMinRate;
private static final String KEY_PEAK_REFRESH_RATE = "peak_refresh_rate";
private static final String KEY_MIN_REFRESH_RATE = "min_refresh_rate";
private Context mContext;
protected static boolean isAppInList = false;
protected static final int STATE_DEFAULT = 0;
protected static final int STATE_STANDARD = 1;
protected static final int STATE_EXTREME = 2;
private static final float REFRESH_STATE_DEFAULT = 120f;
private static final float REFRESH_STATE_STANDARD = 60f;
private static final float REFRESH_STATE_EXTREME = 120f;
private static final String REFRESH_STANDARD = "refresh.standard=";
private static final String REFRESH_EXTREME = "refresh.extreme=";
private SharedPreferences mSharedPrefs;
protected RefreshUtils(Context context) {
mSharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
mContext = context;
}
public static void startService(Context context) {
context.startServiceAsUser(new Intent(context, RefreshService.class),
UserHandle.CURRENT);
}
private void writeValue(String profiles) {
mSharedPrefs.edit().putString(REFRESH_CONTROL, profiles).apply();
}
protected void getOldRate(){
defaultMaxRate = Settings.System.getFloat(mContext.getContentResolver(), KEY_PEAK_REFRESH_RATE, REFRESH_STATE_DEFAULT);
defaultMinRate = Settings.System.getFloat(mContext.getContentResolver(), KEY_MIN_REFRESH_RATE, REFRESH_STATE_DEFAULT);
}
private String getValue() {
String value = mSharedPrefs.getString(REFRESH_CONTROL, null);
if (value == null || value.isEmpty()) {
value = REFRESH_STANDARD + ":" + REFRESH_EXTREME;
writeValue(value);
}
return value;
}
protected void writePackage(String packageName, int mode) {
String value = getValue();
value = value.replace(packageName + ",", "");
String[] modes = value.split(":");
String finalString;
switch (mode) {
case STATE_STANDARD:
modes[0] = modes[0] + packageName + ",";
break;
case STATE_EXTREME:
modes[1] = modes[1] + packageName + ",";
break;
}
finalString = modes[0] + ":" + modes[1];
writeValue(finalString);
}
protected int getStateForPackage(String packageName) {
String value = getValue();
String[] modes = value.split(":");
int state = STATE_DEFAULT;
if (modes[0].contains(packageName + ",")) {
state = STATE_STANDARD;
} else if (modes[1].contains(packageName + ",")) {
state = STATE_EXTREME;
}
return state;
}
protected void setRefreshRate(String packageName) {
String value = getValue();
String modes[];
float maxrate = defaultMaxRate;
float minrate = defaultMinRate;
isAppInList = false;
if (value != null) {
modes = value.split(":");
if (modes[0].contains(packageName + ",")) {
maxrate = REFRESH_STATE_STANDARD;
if ( minrate > maxrate){
minrate = maxrate;
}
isAppInList = true;
} else if (modes[1].contains(packageName + ",")) {
maxrate = REFRESH_STATE_EXTREME;
if ( minrate > maxrate){
minrate = maxrate;
}
isAppInList = true;
}
}
Settings.System.putFloat(mContext.getContentResolver(), KEY_MIN_REFRESH_RATE, minrate);
Settings.System.putFloat(mContext.getContentResolver(), KEY_PEAK_REFRESH_RATE, maxrate);
}
}

View File

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

View File

@@ -0,0 +1,121 @@
/*
* Copyright (C) 2020 Paranoid Android
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.speaker;
import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.AudioAttributes;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragment;
import androidx.preference.SwitchPreference;
import org.lineageos.settings.R;
import java.io.IOException;
public class ClearSpeakerFragment extends PreferenceFragment implements
Preference.OnPreferenceChangeListener {
private static final String TAG = ClearSpeakerFragment.class.getSimpleName();
private static final String PREF_CLEAR_SPEAKER = "clear_speaker_pref";
private AudioManager mAudioManager;
private Handler mHandler;
private MediaPlayer mMediaPlayer;
private SwitchPreference mClearSpeakerPref;
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.clear_speaker_settings);
mClearSpeakerPref = (SwitchPreference) findPreference(PREF_CLEAR_SPEAKER);
mClearSpeakerPref.setOnPreferenceChangeListener(this);
mHandler = new Handler();
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
if (preference == mClearSpeakerPref) {
boolean value = (Boolean) newValue;
if (value) {
if (startPlaying()) {
mHandler.removeCallbacksAndMessages(null);
mHandler.postDelayed(() -> {
stopPlaying();
}, 30000);
return true;
}
}
}
return false;
}
@Override
public void onStop() {
super.onStop();
stopPlaying();
}
public boolean startPlaying() {
mAudioManager.setParameters("status_earpiece_clean=on");
mMediaPlayer = new MediaPlayer();
getActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setLooping(true);
try {
AssetFileDescriptor file = getResources().openRawResourceFd(R.raw.clear_speaker_sound);
try {
mMediaPlayer.setDataSource(file.getFileDescriptor(), file.getStartOffset(), file.getLength());
} finally {
file.close();
}
mClearSpeakerPref.setEnabled(false);
mMediaPlayer.setVolume(1.0f, 1.0f);
mMediaPlayer.prepare();
mMediaPlayer.start();
} catch (IOException ioe) {
Log.e(TAG, "Failed to play speaker clean sound!", ioe);
return false;
}
return true;
}
public void stopPlaying() {
if (mMediaPlayer != null) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer=null;
}
}
mAudioManager.setParameters("status_earpiece_clean=off");
mClearSpeakerPref.setEnabled(true);
mClearSpeakerPref.setChecked(false);
}
}

View File

@@ -0,0 +1,160 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.lineageos.settings.utils;
import android.util.Log;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public final class FileUtils {
private static final String TAG = "FileUtils";
private FileUtils() {
// This class is not supposed to be instantiated
}
/**
* 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;
}
/**
* Writes the given value into the given file
*
* @return true on success, false on failure
*/
public static boolean writeLine(String fileName, String value) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter(new FileWriter(fileName));
writer.write(value);
} catch (FileNotFoundException e) {
Log.w(TAG, "No such file " + fileName + " for writing", e);
return false;
} catch (IOException e) {
Log.e(TAG, "Could not write to file " + fileName, e);
return false;
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException e) {
// Ignored, not much we can do anyway
}
}
return true;
}
/**
* 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();
}
/**
* Deletes an existing file
*
* @return true if the delete was successful, false if not
*/
public static boolean delete(String fileName) {
final File file = new File(fileName);
boolean ok = false;
try {
ok = file.delete();
} catch (SecurityException e) {
Log.w(TAG, "SecurityException trying to delete " + fileName, e);
}
return ok;
}
/**
* Renames an existing file
*
* @return true if the rename was successful, false if not
*/
public static boolean rename(String srcPath, String dstPath) {
final File srcFile = new File(srcPath);
final File dstFile = new File(dstPath);
boolean ok = false;
try {
ok = srcFile.renameTo(dstFile);
} catch (SecurityException e) {
Log.w(TAG, "SecurityException trying to rename " + srcPath + " to " + dstPath, e);
} catch (NullPointerException e) {
Log.e(TAG, "NullPointerException trying to rename " + srcPath + " to " + dstPath, e);
}
return ok;
}
}

View File

@@ -1,6 +1,6 @@
# Fingerprint
persist.vendor.fingerprint.type=udfps_optical
persist.vendor.fingerprint.sensor_location=540|2163|95
persist.vendor.fingerprint.sensor_location=540|2163|107
# Sensors
ro.vendor.sensors.notifier.light_sensors.primary=5

View File

@@ -1,4 +1,4 @@
# All unpinned blobs below are extracted from cupid OS2.0.3.0.VLCMIXM
# All unpinned blobs below are extracted from cupid OS2.0.1.0.VLCMIXM
# ACDB
vendor/etc/acdbdata/Forte_elus/Forte_elus_acdb_cal.acdb:vendor/etc/acdbdata/waipio_mtp/Forte_elus_acdb_cal.acdb
@@ -743,7 +743,7 @@ vendor/lib64/libvidhance_stabilizer.so
vendor/lib64/libvidhance_super_stabilization.so
vendor/lib64/libxmi_hdr_checker.so
vendor/lib64/libxmi_high_dynamic_range.so
vendor/lib64/libxmi_high_dynamic_range_cdsp.so;STRIP_DEBUG_SECTIONS
vendor/lib64/libxmi_high_dynamic_range_cdsp.so
vendor/lib64/libxmi_slow_motion_mein.so
vendor/lib64/vendor.qti.hardware.camera.aon@1.0-service-impl.so
vendor/lib64/vendor.qti.hardware.camera.postproc@1.0-service-impl.so
@@ -878,12 +878,14 @@ vendor/lib64/hw/fingerprint.goodix_fod.so:vendor/lib64/hw/fingerprint.goodix_fod
vendor/lib64/libgf_hal.so
# Graphics (Adreno firmware)
vendor/firmware/a730_sqe.fw
vendor/firmware/a730_zap.b00
vendor/firmware/a730_zap.b01
vendor/firmware/a730_zap.b02
vendor/firmware/a730_zap.elf
vendor/firmware/a730_zap.mbn
vendor/firmware/a730_zap.mdt
vendor/firmware/gmu_gen70000.bin
# NFC configs
vendor/etc/libnfc-nci.conf

View File

@@ -1,5 +1,5 @@
## All proprietary files from this list, unless pinned and noted otherwise,
## are from cupid OS2.0.3.0.VLCMIXM
## are from cupid OS2.0.1.0.VLCMIXM
abl.img;AB
aop.img;AB

View File

@@ -0,0 +1,28 @@
app_domain(devicesettings_app)
# Allow devicesettings_app to find *_service
allow devicesettings_app {
app_api_service
audioserver_service
cameraserver_service
drmserver_service
mediaextractor_service
mediametrics_service
mediaserver_service
}:service_manager find;
# Allow devicesettings_app read and write /data/data subdirectory
allow devicesettings_app system_app_data_file:dir create_dir_perms;
allow devicesettings_app system_app_data_file:{ file lnk_file } create_file_perms;
# Allow binder communication with gpuservice
binder_call(devicesettings_app, gpuservice)
# Allow devicesettings_app to read and write to cgroup/sysfs_leds/sysfs_thermal
allow devicesettings_app sysfs_leds:dir search;
#allow devicesettings_app vendor_sysfs_graphics:dir search;
allow devicesettings_app {
cgroup
sysfs_leds
sysfs_thermal
}:{ file lnk_file } rw_file_perms;

View File

@@ -0,0 +1,2 @@
user=system seinfo=platform name=org.lineageos.settings domain=devicesettings_app type=system_app_data_file
user=system seinfo=platform name=org.lineageos.devicesettings domain=devicesettings_app type=system_app_data_file

View File

@@ -0,0 +1,2 @@
type devicesettings_app, domain;
typeattribute devicesettings_app mlstrustedsubject;

View File

@@ -0,0 +1,11 @@
# MIUI
ro.miui. u:object_r:exported_system_prop:s0
ro.cust.test u:object_r:exported_system_prop:s0
ro.carrier u:object_r:exported_default_prop:s0 exact string
persist.vendor.sensors. u:object_r:exported_system_prop:s0
ro.fota.oem u:object_r:exported_system_prop:s0
persist.camera.capture.misegment.dump u:object_r:exported_system_prop:s0
# Fingerprint
sys.fp.vendor u:object_r:vendor_fingerprint_prop:s0
gf.debug. u:object_r:vendor_fingerprint_prop:s0