Compare commits

..

8 commits

Author SHA1 Message Date
Mukul Dhir
e2fe741e9b
sdm710-common: sepolicy: Allow init to write to proc
01-01 02:13:02.803   344   344 I hwservicemanager: Since android.hardware.keymaster@3.0::IKeymasterDevice/default is not registered, trying to start it as a lazy HAL.
01-01 02:13:02.804   371   371 I HidlServiceManagement: getService: Trying again for android.hardware.keymaster@3.0::IKeymasterDevice/default...
01-01 02:13:02.930     1     1 I init    : type=1400 audit(0.0:37): avc: denied { write } for name="dirty_background_bytes" dev="proc" ino=12937 scontext=u:r:init:s0 tcontext=u:object_r:proc:s0 tclass=file permissive=1
01-01 02:13:02.953     1     1 I init    : type=1400 audit(0.0:38): avc: denied { write } for name="discard_max_bytes" dev="sysfs" ino=20778 scontext=u:r:init:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1
01-01 02:13:02.953     1     1 I init    : type=1400 audit(0.0:39): avc: denied { open } for path="/sys/devices/soc.0/f9824900.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0/queue/discard_max_bytes" dev="sysfs" ino=20778 scontext=u:r:init:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=1

Change-Id: I0283d0744619d82867318879152cd6fbfca094aa
2023-11-13 23:05:34 +02:00
Michael Bestas
d5bc026c92
sdm710-common: sepolicy: legacy: Allow init write to discard_max_bytes
system/core/rootdir/init.rc
1110:    write /dev/sys/block/by-name/userdata/queue/discard_max_bytes 134217728
1111:    write /dev/sys/block/by-name/rootdisk/queue/discard_max_bytes 134217728

Fixes: avc: denied { write } for comm="init" name="discard_max_bytes"
    dev="sysfs" ino=55527 scontext=u:r:init:s0
    tcontext=u:object_r:sysfs:s0 tclass=file permissive=0
2023-11-13 23:05:33 +02:00
Khusika Dhamar Gusti
385565f029
sdm710-common: sepolicy: Address kill denials
Fixes:
avc: denied { kill } for comm="fsck.f2fs" capability=5 scontext=u:r:fsck:s0 tcontext=u:r:fsck:s0 tclass=capability permissive=0

Signed-off-by: Khusika Dhamar Gusti <mail@khusika.dev>
2023-11-13 23:05:33 +02:00
halibw
e80a6564f5
sdm710-common: sepolicy: Allow init to relabelto logdump_partition
Change-Id: I8a3d2c1b0ae6163eb595310e779fa0e74c505da7
2023-11-13 23:05:33 +02:00
Le Hong Duc
50fed07446
sdm660-common: sepolicy: Label logdump partition 2023-11-13 23:05:33 +02:00
4683e63404
sdm710-common: Drop KProfiles
This reverts commit f8e389999a.
2023-11-13 23:05:32 +02:00
Davide Garberi
1bc645396f
sdm710-common: Reserve size for system partition statically
* With the older flag the system space size was being chosen statically,
  this way only the reserved size for Gapps is static while the whole size
  is being dynamically chosen

Change-Id: Ib9a59ab429f725b2f571c8b1d74cec8bb6ab72dc
2023-11-13 23:05:32 +02:00
9bbfd0eac9
sdm710-common: Update fstab, change metadata, update flags 2023-11-13 23:04:44 +02:00
99 changed files with 185343 additions and 708 deletions

View file

@ -4,22 +4,21 @@ COMMON_PATH := device/lenovo/sdm710-common
# Architecture # Architecture
TARGET_ARCH := arm64 TARGET_ARCH := arm64
TARGET_ARCH_VARIANT := armv8-a TARGET_ARCH_VARIANT := armv8-2a
TARGET_CPU_ABI := arm64-v8a TARGET_CPU_ABI := arm64-v8a
TARGET_CPU_ABI2 := TARGET_CPU_ABI2 :=
TARGET_CPU_VARIANT := generic TARGET_CPU_VARIANT := generic
TARGET_CPU_VARIANT_RUNTIME := kryo385 TARGET_CPU_VARIANT_RUNTIME := cortex-a75
TARGET_2ND_ARCH := arm TARGET_2ND_ARCH := arm
TARGET_2ND_ARCH_VARIANT := armv8-a TARGET_2ND_ARCH_VARIANT := armv8-a
TARGET_2ND_CPU_ABI := armeabi-v7a TARGET_2ND_CPU_ABI := armeabi-v7a
TARGET_2ND_CPU_ABI2 := armeabi TARGET_2ND_CPU_ABI2 := armeabi
TARGET_2ND_CPU_VARIANT := generic TARGET_2ND_CPU_VARIANT := generic
TARGET_2ND_CPU_VARIANT_RUNTIME := kryo385 TARGET_2ND_CPU_VARIANT_RUNTIME := cortex-a75
BUILD_BROKEN_DUP_RULES := true BUILD_BROKEN_DUP_RULES := true
BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES := true BUILD_BROKEN_ELF_PREBUILT_PRODUCT_COPY_FILES := true
BUILD_BROKEN_INCORRECT_PARTITION_IMAGES := true
# Bootloader # Bootloader
TARGET_BOOTLOADER_BOARD_NAME := sdm710 TARGET_BOOTLOADER_BOARD_NAME := sdm710
@ -50,6 +49,7 @@ BOARD_KERNEL_TAGS_OFFSET := 0x00000100
BOARD_RAMDISK_OFFSET := 0x01000000 BOARD_RAMDISK_OFFSET := 0x01000000
BOARD_KERNEL_IMAGE_NAME := Image.gz-dtb BOARD_KERNEL_IMAGE_NAME := Image.gz-dtb
BOARD_KERNEL_SEPARATED_DTBO := true BOARD_KERNEL_SEPARATED_DTBO := true
BOARD_RAMDISK_USE_LZ4 := true
TARGET_KERNEL_ARCH := arm64 TARGET_KERNEL_ARCH := arm64
TARGET_KERNEL_SOURCE := kernel/lenovo/sdm710 TARGET_KERNEL_SOURCE := kernel/lenovo/sdm710
TARGET_KERNEL_VERSION := 4.9 TARGET_KERNEL_VERSION := 4.9
@ -79,10 +79,6 @@ BOARD_HAS_QCA_FM_SOC := "cherokee"
# HIDL # HIDL
DEVICE_MANIFEST_FILE := $(COMMON_PATH)/manifest.xml DEVICE_MANIFEST_FILE := $(COMMON_PATH)/manifest.xml
DEVICE_MATRIX_FILE := $(COMMON_PATH)/compatibility_matrix.xml DEVICE_MATRIX_FILE := $(COMMON_PATH)/compatibility_matrix.xml
DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE += \
hardware/qcom-caf/common/vendor_framework_compatibility_matrix.xml \
$(COMMON_PATH)/framework_compatibility_matrix.xml \
vendor/lineage/config/device_framework_matrix.xml
# Partitions # Partitions
BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864 BOARD_BOOTIMAGE_PARTITION_SIZE := 67108864
@ -95,6 +91,7 @@ BOARD_ODMIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4 BOARD_PRODUCTIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := ext4 BOARD_SYSTEM_EXTIMAGE_FILE_SYSTEM_TYPE := ext4
BOARD_FLASH_BLOCK_SIZE := 262144 BOARD_FLASH_BLOCK_SIZE := 262144
BOARD_BUILD_SYSTEM_ROOT_IMAGE := false
TARGET_USERIMAGES_USE_EXT4 := true TARGET_USERIMAGES_USE_EXT4 := true
# Dynamic partitions # Dynamic partitions
@ -102,10 +99,9 @@ BOARD_USES_METADATA_PARTITION := true
BOARD_SUPER_PARTITION_BLOCK_DEVICES := vendor system BOARD_SUPER_PARTITION_BLOCK_DEVICES := vendor system
BOARD_SUPER_PARTITION_METADATA_DEVICE := system BOARD_SUPER_PARTITION_METADATA_DEVICE := system
-include vendor/lineage/config/BoardConfigReservedSize.mk
BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := 1073741824 BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE := 1073741824
BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := 5368709120 BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE := 5368709120
BOARD_SYSTEMIMAGE_PARTITION_RESERVED_SIZE := 500019200
BOARD_SUPER_PARTITION_SIZE := $(shell expr $(BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE) + $(BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE) ) BOARD_SUPER_PARTITION_SIZE := $(shell expr $(BOARD_SUPER_PARTITION_VENDOR_DEVICE_SIZE) + $(BOARD_SUPER_PARTITION_SYSTEM_DEVICE_SIZE) )
BOARD_SUPER_PARTITION_GROUPS := lenovo710_dynpart BOARD_SUPER_PARTITION_GROUPS := lenovo710_dynpart
@ -120,7 +116,6 @@ TARGET_COPY_OUT_SYSTEM_EXT := system_ext
TARGET_ODM_PROP += $(COMMON_PATH)/odm.prop TARGET_ODM_PROP += $(COMMON_PATH)/odm.prop
TARGET_PRODUCT_PROP += $(COMMON_PATH)/product.prop TARGET_PRODUCT_PROP += $(COMMON_PATH)/product.prop
TARGET_SYSTEM_EXT_PROP += $(COMMON_PATH)/system_ext.prop TARGET_SYSTEM_EXT_PROP += $(COMMON_PATH)/system_ext.prop
TARGET_SYSTEM_PROP += $(COMMON_PATH)/system.prop
TARGET_VENDOR_PROP += $(COMMON_PATH)/vendor.prop TARGET_VENDOR_PROP += $(COMMON_PATH)/vendor.prop
# Root # Root
@ -131,7 +126,6 @@ BOARD_ROOT_EXTRA_SYMLINKS := \
/vendor/firmware_mnt:/firmware /vendor/firmware_mnt:/firmware
# Recovery # Recovery
TARGET_RECOVERY_PIXEL_FORMAT := BGRA_8888
TARGET_RECOVERY_FSTAB := $(COMMON_PATH)/rootdir/etc/fstab.qcom TARGET_RECOVERY_FSTAB := $(COMMON_PATH)/rootdir/etc/fstab.qcom
# Releasetools # Releasetools
@ -143,12 +137,8 @@ OVERRIDE_RS_DRIVER := libRSDriver_adreno.so
# RIL # RIL
ENABLE_VENDOR_RIL_SERVICE := true ENABLE_VENDOR_RIL_SERVICE := true
# Security patch level
VENDOR_SECURITY_PATCH := 2020-03-01
# Sepolicy # Sepolicy
TARGET_USES_LOGDUMP_AS_METADATA := true include device/qcom/sepolicy_vndr-legacy-um/SEPolicy.mk
include device/qcom/sepolicy_vndr/SEPolicy.mk
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/private SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/private
BOARD_VENDOR_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/vendor BOARD_VENDOR_SEPOLICY_DIRS += $(COMMON_PATH)/sepolicy/vendor
@ -186,4 +176,4 @@ WPA_SUPPLICANT_VERSION := VER_0_8_X
TARGET_SEC_FP_HAS_FINGERPRINT_GESTURES := true TARGET_SEC_FP_HAS_FINGERPRINT_GESTURES := true
# Inherit from the proprietary version # Inherit from the proprietary version
include vendor/lenovo/sdm710-common/BoardConfigVendor.mk -include vendor/lenovo/sdm710-common/BoardConfigVendor.mk

View file

@ -2,18 +2,18 @@
{ {
"repository": "kernel_lenovo_sdm710", "repository": "kernel_lenovo_sdm710",
"target_path": "kernel/lenovo/sdm710", "target_path": "kernel/lenovo/sdm710",
"branch": "fourteen" "branch": "thirteen"
}, },
{ {
"remote": "pixel-devices-blobs", "remote": "pixel-devices-blobs",
"repository": "vendor_lenovo_sdm710-common", "repository": "vendor_lenovo_sdm710-common",
"target_path": "vendor/lenovo/sdm710-common", "target_path": "vendor/lenovo/sdm710-common",
"branch": "fourteen" "branch": "thirteen"
}, },
{ {
"remote": "pixel-devices-blobs", "remote": "pixel-devices-blobs",
"repository": "vendor_lenovo-firmware", "repository": "vendor_lenovo-firmware",
"target_path": "vendor/lenovo-firmware", "target_path": "vendor/lenovo-firmware",
"branch": "fourteen" "branch": "thirteen"
} }
] ]

View file

@ -58,7 +58,6 @@ It allows additional grants on top of privapp-permissions-platform.xml
<privapp-permissions package="com.qualcomm.wfd.service"> <privapp-permissions package="com.qualcomm.wfd.service">
<permission name="android.permission.READ_FRAME_BUFFER"/> <permission name="android.permission.READ_FRAME_BUFFER"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/> <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
<permission name="android.permission.START_FOREGROUND_SERVICES_FROM_BACKGROUND"/>
</privapp-permissions> </privapp-permissions>
<privapp-permissions package="org.codeaurora.ims"> <privapp-permissions package="org.codeaurora.ims">

View file

@ -61,10 +61,7 @@ fi
function blob_fixup() { function blob_fixup() {
case "${1}" in case "${1}" in
vendor/etc/seccomp_policy/vendor.qti.hardware.dsp.policy) vendor/etc/seccomp_policy/vendor.qti.hardware.dsp.policy)
echo 'madvise: 1' >> "${2}" echo 'madvise: 1' >> ${2}
;;
vendor/lib/libwvhidl.so)
"${PATCHELF}" --replace-needed "libcrypto.so" "libcrypto-v33.so" "${2}"
;; ;;
esac esac
} }

View file

@ -1,100 +0,0 @@
<compatibility-matrix version="2.0" type="framework">
<hal format="hidl" optional="true">
<name>android.hardware.light</name>
<version>2.0</version>
<interface>
<name>ILight</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.vibrator</name>
<version>1.0</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl">
<name>com.qualcomm.qti.ant</name>
<transport>hwbinder</transport>
<version>1.0</version>
<interface>
<name>IAntHci</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>vendor.qti.imsrtpservice</name>
<version>2.0-1</version>
<version>3.0</version>
<interface>
<name>IRTPService</name>
<instance>imsrtpservice</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.wifi</name>
<interface>
<name>IWifi</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.cas</name>
<interface>
<name>IMediaCasService</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.drm</name>
<interface>
<name>IDrmFactory</name>
<instance>clearkey</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.power</name>
<interface>
<name>IPower</name>
<instance>default</instance>
</interface>
</hal>
<hal format="hidl" optional="true">
<name>android.hardware.usb</name>
<version>1.0-3</version>
<interface>
<name>IUsb</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.vibrator</name>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.wifi</name>
<interface>
<name>IWifi</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.wifi.hostapd</name>
<interface>
<name>IHostapd</name>
<instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.wifi.supplicant</name>
<interface>
<name>ISupplicant</name>
<instance>default</instance>
</interface>
</hal>
</compatibility-matrix>

View file

@ -1,4 +1,4 @@
<manifest version="1.0" type="device" target-level="5"> <manifest version="1.0" type="device" target-level="4">
<hal format="hidl"> <hal format="hidl">
<name>android.hardware.audio</name> <name>android.hardware.audio</name>
<transport>hwbinder</transport> <transport>hwbinder</transport>
@ -19,6 +19,16 @@
</interface> </interface>
<fqname>@6.0::IEffectsFactory/default</fqname> <fqname>@6.0::IEffectsFactory/default</fqname>
</hal> </hal>
<hal format="hidl">
<name>android.hardware.biometrics.fingerprint</name>
<transport>hwbinder</transport>
<version>2.1</version>
<interface>
<name>IBiometricsFingerprint</name>
<instance>default</instance>
</interface>
<fqname>@2.1::IBiometricsFingerprint/default</fqname>
</hal>
<hal format="hidl"> <hal format="hidl">
<name>android.hardware.bluetooth</name> <name>android.hardware.bluetooth</name>
<transport>hwbinder</transport> <transport>hwbinder</transport>
@ -631,13 +641,12 @@
</interface> </interface>
</hal> </hal>
<hal format="hidl"> <hal format="hidl">
<name>vendor.qti.hardware.data.iwlan</name> <name>android.hardware.health</name>
<transport>hwbinder</transport> <transport>hwbinder</transport>
<version>1.0</version> <version>2.1</version>
<interface> <interface>
<name>IIWlan</name> <name>IHealth</name>
<instance>slot1</instance> <instance>default</instance>
<instance>slot2</instance>
</interface> </interface>
</hal> </hal>
</manifest> </manifest>

View file

@ -315,6 +315,11 @@
<item>35</item> <item>35</item>
</integer-array> </integer-array>
<!-- Vibrator pattern for a very short but reliable vibration for soft keyboard tap -->
<integer-array name="config_keyboardTapVibePattern">
<item>40</item>
</integer-array>
<!-- Default list of files pinned by the Pinner Service --> <!-- Default list of files pinned by the Pinner Service -->
<string-array translatable="false" name="config_defaultPinnerServiceFiles"> <string-array translatable="false" name="config_defaultPinnerServiceFiles">
<item>"/system/framework/framework.jar"</item> <item>"/system/framework/framework.jar"</item>
@ -385,7 +390,7 @@
<string ...>M -5,0 L -5,10 L 5,10 L 5,0 Z @dp</string> <string ...>M -5,0 L -5,10 L 5,10 L 5,0 Z @dp</string>
@see https://www.w3.org/TR/SVG/paths.html#PathData @see https://www.w3.org/TR/SVG/paths.html#PathData
--> -->
<string translatable="false" name="config_mainBuiltInDisplayCutout">M -100,0 L -40,82 L 40,82 L 100,0 Z</string> <string translatable="false" name="config_mainBuiltInDisplayCutout">M -80,0 L -80,80 L 80,80 L 80,0 Z</string>
<!-- Height of the status bar --> <!-- Height of the status bar -->
<dimen name="status_bar_height">88.0px</dimen> <dimen name="status_bar_height">88.0px</dimen>
@ -399,6 +404,14 @@
The default is false. --> The default is false. -->
<bool name="config_lidControlsSleep">true</bool> <bool name="config_lidControlsSleep">true</bool>
<!-- List of biometric sensors on the device, in decreasing strength. Consumed by AuthService
when registering authenticators with BiometricService. Format must be ID:Modality:Strength,
where: IDs are unique per device, Modality as defined in BiometricAuthenticator.java,
and Strength as defined in Authenticators.java -->
<string-array name="config_biometric_sensors" translatable="false" >
<item>0:2:15</item> <!-- ID0:Fingerprint:Strong -->
</string-array>
<!-- SQLite --> <!-- SQLite -->
<string name="db_default_journal_mode">MEMORY</string> <string name="db_default_journal_mode">MEMORY</string>
<string name="db_default_sync_mode">OFF</string> <string name="db_default_sync_mode">OFF</string>
@ -419,6 +432,9 @@
2: gestures only for back, home and overview --> 2: gestures only for back, home and overview -->
<integer name="config_navBarInteractionMode">2</integer> <integer name="config_navBarInteractionMode">2</integer>
<!-- Specify if the fingerprint hardware support gestures-->
<bool name="config_fingerprintSupportsGestures">true</bool>
<!-- Enable system navigation keys. --> <!-- Enable system navigation keys. -->
<bool name="config_supportSystemNavigationKeys">true</bool> <bool name="config_supportSystemNavigationKeys">true</bool>
@ -483,16 +499,4 @@
<!-- Whether to show the Preference for Adaptive connectivity --> <!-- Whether to show the Preference for Adaptive connectivity -->
<bool name="config_show_adaptive_connectivity">false</bool> <bool name="config_show_adaptive_connectivity">false</bool>
<!-- Enable Night display, which requires HWC 2.0. -->
<bool name="config_nightDisplayAvailable">true</bool>
<!-- Boolean indicating whether the HWC setColorTransform function can be performed efficiently
in hardware. -->
<bool name="config_setColorTransformAccelerated">true</bool>
<!-- Enables or disables fading edges when marquee is enabled in TextView.
Off by default, since the framebuffer readback used to implement the
fading edges is prohibitively expensive on most GPUs. -->
<bool name="config_ui_enableFadingMarquee">true</bool>
</resources> </resources>

16
pocketmode/Android.mk Normal file
View file

@ -0,0 +1,16 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := LenovoPocketMode
LOCAL_CERTIFICATE := platform
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_PRIVILEGED_MODULE := true
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
include $(BUILD_PACKAGE)

View file

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The CyanogenMod Project
Copyright (C) 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.pocketmode"
android:versionCode="1"
android:versionName="1.0"
android:sharedUserId="android.uid.system">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-sdk
android:minSdkVersion="27" />
<application
android:label="LenovoPocketMode"
android:persistent="true">
<receiver android:name=".BootCompletedReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</receiver>
<service android:name=".PocketModeService"
android:permission="PocketModeService">
</service>
</application>
</manifest>

View file

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

View file

@ -0,0 +1,36 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* 2017 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.pocketmode;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.util.Log;
public class BootCompletedReceiver extends BroadcastReceiver {
private static final String TAG = "LenovoPocketMode";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Starting");
context.startServiceAsUser(new Intent(context, PocketModeService.class),
UserHandle.CURRENT);
}
}

View file

@ -0,0 +1,84 @@
/*
* Copyright (C) 2016 The CyanogenMod Project
* 2017 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.pocketmode;
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 PocketModeService extends Service {
private static final String TAG = "PocketModeService";
private static final boolean DEBUG = false;
private ProximitySensor mProximitySensor;
@Override
public void onCreate() {
if (DEBUG) Log.d(TAG, "Creating service");
mProximitySensor = new ProximitySensor(this);
IntentFilter screenStateFilter = new IntentFilter();
screenStateFilter.addAction(Intent.ACTION_SCREEN_OFF);
screenStateFilter.addAction(Intent.ACTION_USER_PRESENT);
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");
this.unregisterReceiver(mScreenStateReceiver);
mProximitySensor.disable();
super.onDestroy();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private void onDeviceUnlocked() {
if (DEBUG) Log.d(TAG, "Device unlocked");
mProximitySensor.disable();
}
private void onDisplayOff() {
if (DEBUG) Log.d(TAG, "Display off");
mProximitySensor.enable();
}
private BroadcastReceiver mScreenStateReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_USER_PRESENT)) {
onDeviceUnlocked();
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
onDisplayOff();
}
}
};
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2016 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.pocketmode;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.FileUtils;
import android.util.Log;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ProximitySensor implements SensorEventListener {
private static final String TAG = "PocketModeProximity";
private static final boolean DEBUG = false;
private ExecutorService mExecutorService;
private Context mContext;
private Sensor mSensor;
private SensorManager mSensorManager;
public ProximitySensor(Context context) {
mContext = context;
mSensorManager = mContext.getSystemService(SensorManager.class);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
mExecutorService = Executors.newSingleThreadExecutor();
}
private Future<?> submit(Runnable runnable) {
return mExecutorService.submit(runnable);
}
@Override
public void onSensorChanged(SensorEvent event) {
/* Empty */
}
@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);
});
}
}

118
power-libperfmgr/Android.bp Normal file
View file

@ -0,0 +1,118 @@
//
// Copyright (C) 2018 The Android Open Source 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 {
default_applicable_licenses: ["Android-Apache-2.0"],
}
cc_library {
name: "libdisppower-lenovo-sdm710",
proprietary: true,
srcs: [
"disp-power/DisplayLowPower.cpp",
"disp-power/InteractionHandler.cpp",
],
shared_libs: [
"libbase",
"libcutils",
"liblog",
"libperfmgr",
"libutils",
],
}
cc_library {
name: "libadaptivecpu-lenovo-sdm710",
proprietary: true,
vendor: true,
srcs: [
"adaptivecpu/AdaptiveCpu.cpp",
"adaptivecpu/AdaptiveCpuConfig.cpp",
"adaptivecpu/AdaptiveCpuStats.cpp",
"adaptivecpu/CpuFrequencyReader.cpp",
"adaptivecpu/CpuLoadReaderProcStat.cpp",
"adaptivecpu/CpuLoadReaderSysDevices.cpp",
"adaptivecpu/Device.cpp",
"adaptivecpu/KernelCpuFeatureReader.cpp",
"adaptivecpu/Model.cpp",
"adaptivecpu/RealFilesystem.cpp",
"adaptivecpu/ThrottleDecision.cpp",
"adaptivecpu/TimeSource.cpp",
"adaptivecpu/WorkDurationProcessor.cpp",
],
shared_libs: [
"android.hardware.power-V3-ndk",
"libbase",
"liblog",
"libperfmgr",
"libutils",
"libcutils",
],
}
cc_test {
name: "libadaptivecpu_test-lenovo-sdm710",
proprietary: true,
vendor: true,
srcs: [
"adaptivecpu/tests/AdaptiveCpuConfigTest.cpp",
"adaptivecpu/tests/AdaptiveCpuStatsTest.cpp",
"adaptivecpu/tests/CpuFrequencyReaderTest.cpp",
"adaptivecpu/tests/CpuLoadReaderProcStatTest.cpp",
"adaptivecpu/tests/CpuLoadReaderSysDevicesTest.cpp",
"adaptivecpu/tests/KernelCpuFeatureReaderTest.cpp",
"adaptivecpu/tests/ModelTest.cpp",
"adaptivecpu/tests/WorkDurationProcessorTest.cpp",
],
static_libs: [
"libadaptivecpu-lenovo-sdm710",
"libgmock",
"android.hardware.power-V3-ndk",
],
shared_libs: [
"liblog",
"libbase",
"libcutils",
],
test_suites: ["device-tests"],
}
cc_binary {
name: "android.hardware.power-service.lenovo-sdm710-libperfmgr",
relative_install_path: "hw",
init_rc: ["aidl/android.hardware.power-service.lenovo-sdm710-libperfmgr.rc"],
vintf_fragments: ["aidl/android.hardware.power-service.lenovo-sdm710.xml"],
vendor: true,
shared_libs: [
"android.hardware.power-V3-ndk",
"libadaptivecpu-lenovo-sdm710",
"libbase",
"libcutils",
"liblog",
"libutils",
"libbinder_ndk",
"libdisppower-lenovo-sdm710",
"libperfmgr",
"libprocessgroup",
"pixel-power-ext-V1-ndk",
],
srcs: [
"aidl/service.cpp",
"aidl/Power.cpp",
"aidl/PowerExt.cpp",
"aidl/PowerHintSession.cpp",
"aidl/PowerSessionManager.cpp",
],
}

View file

@ -1,54 +0,0 @@
#
# 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.
#
ifneq (,$(findstring hardware/google/interfaces, $(PRODUCT_SOONG_NAMESPACES)))
ifneq (,$(findstring hardware/google/pixel, $(PRODUCT_SOONG_NAMESPACES)))
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SHARED_LIBRARIES := \
android.hardware.power-V2-ndk \
libbase \
libbinder_ndk \
libcutils \
libdl \
liblog \
libperfmgr \
libprocessgroup \
libutils \
pixel-power-ext-V1-ndk
LOCAL_SRC_FILES := \
service.cpp \
InteractionHandler.cpp \
Power.cpp \
PowerExt.cpp \
PowerHintSession.cpp \
PowerSessionManager.cpp
LOCAL_CFLAGS := -Wno-unused-parameter -Wno-unused-variable
ifneq ($(TARGET_POWERHAL_MODE_EXT),)
LOCAL_CFLAGS += -DMODE_EXT
LOCAL_SRC_FILES += ../../../../$(TARGET_POWERHAL_MODE_EXT)
endif
ifneq ($(TARGET_TAP_TO_WAKE_NODE),)
LOCAL_CFLAGS += -DTAP_TO_WAKE_NODE=\"$(TARGET_TAP_TO_WAKE_NODE)\"
endif
LOCAL_MODULE := android.hardware.power-service.xiaomi-libperfmgr
LOCAL_INIT_RC := android.hardware.power-service.xiaomi-libperfmgr.rc
LOCAL_MODULE_TAGS := optional
LOCAL_VENDOR_MODULE := true
LOCAL_VINTF_FRAGMENTS := android.hardware.power-service.xiaomi.xml
include $(BUILD_EXECUTABLE)
endif
endif

View file

@ -0,0 +1,233 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "AdaptiveCpu.h"
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <perfmgr/HintManager.h>
#include <sys/resource.h>
#include <utils/Trace.h>
#include <chrono>
#include <deque>
#include <numeric>
#include "CpuLoadReaderSysDevices.h"
#include "Model.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
using ::android::perfmgr::HintManager;
// We pass the previous N ModelInputs to the model, including the most recent ModelInput.
constexpr uint32_t kNumHistoricalModelInputs = 3;
// TODO(b/207662659): Add config for changing between different reader types.
AdaptiveCpu::AdaptiveCpu() {}
bool AdaptiveCpu::IsEnabled() const {
return mIsEnabled;
}
void AdaptiveCpu::HintReceived(bool enable) {
ATRACE_CALL();
LOG(INFO) << "AdaptiveCpu received hint: enable=" << enable;
if (enable) {
StartThread();
} else {
SuspendThread();
}
}
void AdaptiveCpu::StartThread() {
ATRACE_CALL();
std::lock_guard lock(mThreadCreationMutex);
LOG(INFO) << "Starting AdaptiveCpu thread";
mIsEnabled = true;
mShouldReloadConfig = true;
mLastEnabledHintTime = mTimeSource.GetTime();
if (!mLoopThread.joinable()) {
mLoopThread = std::thread([&]() {
pthread_setname_np(pthread_self(), "AdaptiveCpu");
// Parent threads may have higher priorities, so we reset to the default.
int ret = setpriority(PRIO_PROCESS, 0, 0);
if (ret != 0) {
PLOG(ERROR) << "setpriority on AdaptiveCpu thread failed: " << ret;
}
LOG(INFO) << "Started AdaptiveCpu thread successfully";
RunMainLoop();
LOG(ERROR) << "AdaptiveCpu thread ended, this should never happen!";
});
}
}
void AdaptiveCpu::SuspendThread() {
ATRACE_CALL();
LOG(INFO) << "Stopping AdaptiveCpu thread";
// This stops the thread from receiving work durations in ReportWorkDurations, which means the
// thread blocks indefinitely.
mIsEnabled = false;
}
void AdaptiveCpu::ReportWorkDurations(const std::vector<WorkDuration> &workDurations,
std::chrono::nanoseconds targetDuration) {
ATRACE_CALL();
if (!mIsEnabled) {
return;
}
if (!mWorkDurationProcessor.ReportWorkDurations(workDurations, targetDuration)) {
mIsEnabled = false;
return;
}
mWorkDurationsAvailableCondition.notify_one();
}
void AdaptiveCpu::WaitForEnabledAndWorkDurations() {
ATRACE_CALL();
std::unique_lock<std::mutex> lock(mWaitMutex);
// TODO(b/188770301) Once the gating logic is implemented, don't block indefinitely.
mWorkDurationsAvailableCondition.wait(
lock, [&] { return mIsEnabled && mWorkDurationProcessor.HasWorkDurations(); });
}
void AdaptiveCpu::RunMainLoop() {
ATRACE_CALL();
std::deque<ModelInput> historicalModelInputs;
ThrottleDecision previousThrottleDecision = ThrottleDecision::NO_THROTTLE;
while (true) {
ATRACE_NAME("loop");
WaitForEnabledAndWorkDurations();
if (mLastEnabledHintTime + mConfig.enabledHintTimeout < mTimeSource.GetTime()) {
LOG(INFO) << "Adaptive CPU hint timed out, last enabled time="
<< mLastEnabledHintTime.count() << "ns";
mIsEnabled = false;
continue;
}
if (mShouldReloadConfig) {
if (!AdaptiveCpuConfig::ReadFromSystemProperties(&mConfig)) {
mIsEnabled = false;
continue;
}
LOG(INFO) << "Read config: " << mConfig;
mShouldReloadConfig = false;
}
ATRACE_BEGIN("compute");
mAdaptiveCpuStats.RegisterStartRun();
if (!mIsInitialized) {
if (!mKernelCpuFeatureReader.Init()) {
mIsEnabled = false;
continue;
}
mDevice = ReadDevice();
mIsInitialized = true;
}
ModelInput modelInput;
modelInput.previousThrottleDecision = previousThrottleDecision;
modelInput.workDurationFeatures = mWorkDurationProcessor.GetFeatures();
LOG(VERBOSE) << "Got work durations: count=" << modelInput.workDurationFeatures.numDurations
<< ", average=" << modelInput.workDurationFeatures.averageDuration.count()
<< "ns";
if (modelInput.workDurationFeatures.numDurations == 0) {
continue;
}
if (!mKernelCpuFeatureReader.GetRecentCpuFeatures(&modelInput.cpuPolicyAverageFrequencyHz,
&modelInput.cpuCoreIdleTimesPercentage)) {
mIsEnabled = false;
continue;
}
modelInput.LogToAtrace();
historicalModelInputs.push_back(modelInput);
if (historicalModelInputs.size() > kNumHistoricalModelInputs) {
historicalModelInputs.pop_front();
}
const ThrottleDecision throttleDecision = mModel.Run(historicalModelInputs, mConfig);
LOG(VERBOSE) << "Model decision: " << static_cast<uint32_t>(throttleDecision);
ATRACE_INT("AdaptiveCpu_throttleDecision", static_cast<uint32_t>(throttleDecision));
{
ATRACE_NAME("sendHints");
const auto now = mTimeSource.GetTime();
// Resend the throttle hints, even if they've not changed, if the previous send is close
// to timing out. We define "close to" as half the hint timeout, as we can't guarantee
// we will run again before the actual timeout.
const bool throttleHintMayTimeout =
now - mLastThrottleHintTime > mConfig.hintTimeout / 2;
if (throttleDecision != previousThrottleDecision || throttleHintMayTimeout) {
ATRACE_NAME("sendNewHints");
mLastThrottleHintTime = now;
for (const auto &hintName : THROTTLE_DECISION_TO_HINT_NAMES.at(throttleDecision)) {
HintManager::GetInstance()->DoHint(hintName, mConfig.hintTimeout);
}
}
if (throttleDecision != previousThrottleDecision) {
ATRACE_NAME("endOldHints");
for (const auto &hintName :
THROTTLE_DECISION_TO_HINT_NAMES.at(previousThrottleDecision)) {
HintManager::GetInstance()->EndHint(hintName);
}
previousThrottleDecision = throttleDecision;
}
}
mAdaptiveCpuStats.RegisterSuccessfulRun(previousThrottleDecision, throttleDecision,
modelInput.workDurationFeatures, mConfig);
ATRACE_END(); // compute
{
ATRACE_NAME("sleep");
std::this_thread::sleep_for(mConfig.iterationSleepDuration);
}
}
}
void AdaptiveCpu::DumpToFd(int fd) const {
std::stringstream result;
result << "========== Begin Adaptive CPU stats ==========\n";
result << "Enabled: " << mIsEnabled << "\n";
result << "Config: " << mConfig << "\n";
mKernelCpuFeatureReader.DumpToStream(result);
mAdaptiveCpuStats.DumpToStream(result);
result << "========== End Adaptive CPU stats ==========\n";
if (!::android::base::WriteStringToFd(result.str(), fd)) {
PLOG(ERROR) << "Failed to dump state to fd";
}
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,112 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#pragma once
#include <aidl/android/hardware/power/WorkDuration.h>
#include <perfmgr/HintManager.h>
#include <chrono>
#include <thread>
#include <unordered_map>
#include <vector>
#include "AdaptiveCpuConfig.h"
#include "AdaptiveCpuStats.h"
#include "Device.h"
#include "KernelCpuFeatureReader.h"
#include "Model.h"
#include "WorkDurationProcessor.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
using std::chrono_literals::operator""ms;
using ::aidl::android::hardware::power::WorkDuration;
using ::android::perfmgr::HintManager;
// Applies CPU frequency hints infered by an ML model based on the recent CPU statistics and work
// durations.
// This class's public members are not synchronised and should not be used from multiple threads,
// with the exception of ReportWorkDuration, which can be called from an arbitrary thread.
class AdaptiveCpu {
public:
AdaptiveCpu();
bool IsEnabled() const;
// Called when the Adaptive CPU hint is received. This method enables/disables the Adaptive CPU
// thread.
void HintReceived(bool enable);
// Reports work durations for processing. This method returns immediately as work durations are
// processed asynchonuously.
void ReportWorkDurations(const std::vector<WorkDuration> &workDurations,
std::chrono::nanoseconds targetDuration);
// Dump info to a file descriptor. Called when dumping service info.
void DumpToFd(int fd) const;
// When PowerExt receives a hint with this name, HintReceived() is called.
static constexpr char HINT_NAME[] = "ADAPTIVE_CPU";
private:
void StartThread();
void SuspendThread();
// The main loop of Adaptive CPU, which runs in a separate thread.
void RunMainLoop();
void WaitForEnabledAndWorkDurations();
Model mModel;
WorkDurationProcessor mWorkDurationProcessor;
KernelCpuFeatureReader mKernelCpuFeatureReader;
AdaptiveCpuStats mAdaptiveCpuStats;
const TimeSource mTimeSource;
// The thread in which work durations are processed.
std::thread mLoopThread;
// Guards against creating multiple threads in the case HintReceived(true) is called on separate
// threads simultaneously.
std::mutex mThreadCreationMutex;
// Used when waiting in WaitForEnabledAndWorkDurations().
std::mutex mWaitMutex;
// A condition variable that will be notified when new work durations arrive.
std::condition_variable mWorkDurationsAvailableCondition;
volatile bool mIsEnabled = false;
bool mIsInitialized = false;
volatile bool mShouldReloadConfig = false;
std::chrono::nanoseconds mLastEnabledHintTime;
std::chrono::nanoseconds mLastThrottleHintTime;
Device mDevice;
AdaptiveCpuConfig mConfig = AdaptiveCpuConfig::DEFAULT;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,174 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "AdaptiveCpuConfig.h"
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <inttypes.h>
#include <utils/Trace.h>
#include <sstream>
#include <string>
#include <string_view>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
using std::chrono_literals::operator""ms;
using std::chrono_literals::operator""min;
constexpr std::string_view kIterationSleepDurationProperty(
"debug.adaptivecpu.iteration_sleep_duration_ms");
static const std::chrono::milliseconds kIterationSleepDurationMin = 20ms;
constexpr std::string_view kHintTimeoutProperty("debug.adaptivecpu.hint_timeout_ms");
// "percent" as range is 0-100, while the in-memory is "probability" as range is 0-1.
constexpr std::string_view kRandomThrottleDecisionPercentProperty(
"debug.adaptivecpu.random_throttle_decision_percent");
constexpr std::string_view kRandomThrottleOptionsProperty(
"debug.adaptivecpu.random_throttle_options");
constexpr std::string_view kEnabledHintTimeoutProperty("debug.adaptivecpu.enabled_hint_timeout_ms");
bool ParseThrottleDecisions(const std::string &input, std::vector<ThrottleDecision> *output);
std::string FormatThrottleDecisions(const std::vector<ThrottleDecision> &throttleDecisions);
const AdaptiveCpuConfig AdaptiveCpuConfig::DEFAULT{
// N.B.: The model will typically be trained with this value set to 25ms. We set it to 1s as
// a safety measure, but best performance will be seen at 25ms.
.iterationSleepDuration = 1000ms,
.hintTimeout = 2000ms,
.randomThrottleDecisionProbability = 0,
.randomThrottleOptions = {ThrottleDecision::NO_THROTTLE, ThrottleDecision::THROTTLE_50,
ThrottleDecision::THROTTLE_60, ThrottleDecision::THROTTLE_70,
ThrottleDecision::THROTTLE_80, ThrottleDecision::THROTTLE_90},
.enabledHintTimeout = 120min,
};
bool AdaptiveCpuConfig::ReadFromSystemProperties(AdaptiveCpuConfig *output) {
ATRACE_CALL();
output->iterationSleepDuration = std::chrono::milliseconds(
::android::base::GetUintProperty<uint32_t>(kIterationSleepDurationProperty.data(),
DEFAULT.iterationSleepDuration.count()));
output->iterationSleepDuration =
std::max(output->iterationSleepDuration, kIterationSleepDurationMin);
output->hintTimeout = std::chrono::milliseconds(::android::base::GetUintProperty<uint32_t>(
kHintTimeoutProperty.data(), DEFAULT.hintTimeout.count()));
output->randomThrottleDecisionProbability =
static_cast<double>(::android::base::GetUintProperty<uint32_t>(
kRandomThrottleDecisionPercentProperty.data(),
DEFAULT.randomThrottleDecisionProbability * 100)) /
100;
if (output->randomThrottleDecisionProbability > 1.0) {
LOG(ERROR) << "Received bad value for " << kRandomThrottleDecisionPercentProperty << ": "
<< output->randomThrottleDecisionProbability;
return false;
}
const std::string randomThrottleOptionsStr =
::android::base::GetProperty(kRandomThrottleOptionsProperty.data(),
FormatThrottleDecisions(DEFAULT.randomThrottleOptions));
output->randomThrottleOptions.clear();
if (!ParseThrottleDecisions(randomThrottleOptionsStr, &output->randomThrottleOptions)) {
return false;
}
output->enabledHintTimeout =
std::chrono::milliseconds(::android::base::GetUintProperty<uint32_t>(
kEnabledHintTimeoutProperty.data(), DEFAULT.enabledHintTimeout.count()));
return true;
}
bool AdaptiveCpuConfig::operator==(const AdaptiveCpuConfig &other) const {
return iterationSleepDuration == other.iterationSleepDuration &&
hintTimeout == other.hintTimeout &&
randomThrottleDecisionProbability == other.randomThrottleDecisionProbability &&
enabledHintTimeout == other.enabledHintTimeout &&
randomThrottleOptions == other.randomThrottleOptions;
}
std::ostream &operator<<(std::ostream &stream, const AdaptiveCpuConfig &config) {
stream << "AdaptiveCpuConfig(";
stream << "iterationSleepDuration=" << config.iterationSleepDuration.count() << "ms, ";
stream << "hintTimeout=" << config.hintTimeout.count() << "ms, ";
stream << "randomThrottleDecisionProbability=" << config.randomThrottleDecisionProbability
<< ", ";
stream << "enabledHintTimeout=" << config.enabledHintTimeout.count() << "ms, ";
stream << "randomThrottleOptions=[" << FormatThrottleDecisions(config.randomThrottleOptions)
<< "]";
stream << ")";
return stream;
}
bool ParseThrottleDecisions(const std::string &input, std::vector<ThrottleDecision> *output) {
std::stringstream ss(input);
while (ss.good()) {
std::string throttleDecisionStr;
if (std::getline(ss, throttleDecisionStr, ',').fail()) {
LOG(ERROR) << "Failed to getline on throttle decisions string: " << input;
return false;
}
uint32_t throttleDecisionInt;
int scanEnd;
if (std::sscanf(throttleDecisionStr.c_str(), "%" PRIu32 "%n", &throttleDecisionInt,
&scanEnd) != 1 ||
scanEnd != throttleDecisionStr.size()) {
LOG(ERROR) << "Failed to parse as int: str=" << throttleDecisionStr
<< ", input=" << input << ", scanEnd=" << scanEnd;
return false;
}
if (throttleDecisionInt < static_cast<uint32_t>(ThrottleDecision::FIRST) ||
throttleDecisionInt > static_cast<uint32_t>(ThrottleDecision::LAST)) {
LOG(ERROR) << "Failed to parse throttle decision: throttleDecision="
<< throttleDecisionInt << ", input=" << input;
return false;
}
output->push_back(static_cast<ThrottleDecision>(throttleDecisionInt));
}
if (output->empty()) {
LOG(ERROR) << "Failed to find any throttle decisions, must have at least one: " << input;
return false;
}
return true;
}
std::string FormatThrottleDecisions(const std::vector<ThrottleDecision> &throttleDecisions) {
std::stringstream ss;
for (size_t i = 0; i < throttleDecisions.size(); i++) {
ss << static_cast<uint32_t>(throttleDecisions[i]);
if (i < throttleDecisions.size() - 1) {
ss << ",";
}
}
return ss.str();
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,58 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#pragma once
#include <chrono>
#include <iostream>
#include "ThrottleDecision.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
struct AdaptiveCpuConfig {
static bool ReadFromSystemProperties(AdaptiveCpuConfig *output);
static const AdaptiveCpuConfig DEFAULT;
// How long to sleep for between Adaptive CPU runs.
std::chrono::milliseconds iterationSleepDuration;
// Timeout applied to hints. If Adaptive CPU doesn't receive any frames in this time, CPU
// throttling hints are cancelled.
std::chrono::milliseconds hintTimeout;
// Instead of throttling based on model output, choose a random throttle X% of the time. Must be
// between 0 and 1 inclusive.
double randomThrottleDecisionProbability;
std::vector<ThrottleDecision> randomThrottleOptions;
// Setting AdaptiveCpu to enabled only lasts this long. For a continuous run, AdaptiveCpu needs
// to receive the enabled hint more frequently than this value.
std::chrono::milliseconds enabledHintTimeout;
bool operator==(const AdaptiveCpuConfig &other) const;
};
std::ostream &operator<<(std::ostream &os, const AdaptiveCpuConfig &config);
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,131 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "AdaptiveCpuStats.h"
#include <utils/Trace.h>
#include "AdaptiveCpu.h"
using std::chrono_literals::operator""ns;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
void AdaptiveCpuStats::RegisterStartRun() {
ATRACE_CALL();
mNumStartedRuns++;
mLastRunStartTime = mTimeSource->GetTime();
if (mStartTime == 0ns) {
mStartTime = mLastRunStartTime;
}
}
void AdaptiveCpuStats::RegisterSuccessfulRun(ThrottleDecision previousThrottleDecision,
ThrottleDecision throttleDecision,
WorkDurationFeatures workDurationFeatures,
const AdaptiveCpuConfig &config) {
ATRACE_CALL();
mNumSuccessfulRuns++;
mNumThrottles[throttleDecision]++;
const auto runSuccessTime = mTimeSource->GetTime();
mTotalRunDuration += runSuccessTime - mLastRunStartTime;
// Don't update previousThrottleDecision entries if we haven't run successfully before.
if (mLastRunSuccessTime != 0ns) {
mThrottleDurations[previousThrottleDecision] +=
std::min(runSuccessTime - mLastRunSuccessTime,
std::chrono::duration_cast<std::chrono::nanoseconds>(config.hintTimeout));
mNumDurations[previousThrottleDecision] += workDurationFeatures.numDurations;
mNumMissedDeadlines[previousThrottleDecision] += workDurationFeatures.numMissedDeadlines;
}
mLastRunSuccessTime = runSuccessTime;
}
void AdaptiveCpuStats::DumpToStream(std::ostream &stream) const {
stream << "Stats:\n";
stream << "- Successful runs / total runs: " << mNumSuccessfulRuns << " / " << mNumStartedRuns
<< "\n";
stream << "- Total run duration: " << FormatDuration(mTotalRunDuration) << "\n";
stream << "- Average run duration: " << FormatDuration(mTotalRunDuration / mNumSuccessfulRuns)
<< "\n";
stream << "- Running time fraction: "
<< static_cast<double>(mTotalRunDuration.count()) /
(mTimeSource->GetTime() - mStartTime).count()
<< "\n";
stream << "- Number of throttles:\n";
size_t totalNumThrottles = 0;
for (const auto &[throttleDecision, numThrottles] : mNumThrottles) {
stream << " - " << ThrottleString(throttleDecision) << ": " << numThrottles << "\n";
totalNumThrottles += numThrottles;
}
stream << " - Total: " << totalNumThrottles << "\n";
stream << "- Time spent throttling:\n";
std::chrono::nanoseconds totalThrottleDuration;
for (const auto &[throttleDecision, throttleDuration] : mThrottleDurations) {
stream << " - " << ThrottleString(throttleDecision) << ": "
<< FormatDuration(throttleDuration) << "\n";
totalThrottleDuration += throttleDuration;
}
stream << " - Total: " << FormatDuration(totalThrottleDuration) << "\n";
stream << "- Missed deadlines per throttle:\n";
size_t totalNumDurations = 0;
size_t totalNumMissedDeadlines = 0;
for (const auto &[throttleDecision, numDurations] : mNumDurations) {
const size_t numMissedDeadlines = mNumMissedDeadlines.at(throttleDecision);
stream << " - " << ThrottleString(throttleDecision) << ": " << numMissedDeadlines << " / "
<< numDurations << " (" << static_cast<double>(numMissedDeadlines) / numDurations
<< ")\n";
totalNumDurations += numDurations;
totalNumMissedDeadlines += numMissedDeadlines;
}
stream << " - Total: " << totalNumMissedDeadlines << " / " << totalNumDurations << " ("
<< static_cast<double>(totalNumMissedDeadlines) / totalNumDurations << ")\n";
}
std::string AdaptiveCpuStats::FormatDuration(std::chrono::nanoseconds duration) {
double count = static_cast<double>(duration.count());
std::string suffix;
if (count < 1000.0) {
suffix = "ns";
} else if (count < 1000.0 * 1000) {
suffix = "us";
count /= 1000;
} else if (count < 1000.0 * 1000 * 100) {
suffix = "ms";
count /= 1000 * 1000;
} else {
suffix = "s";
count /= 1000 * 1000 * 1000;
}
return std::to_string(count) + suffix;
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,73 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#pragma once
#include <ostream>
#include "AdaptiveCpuConfig.h"
#include "ITimeSource.h"
#include "Model.h"
#include "TimeSource.h"
#include "WorkDurationProcessor.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
// Collects statistics about Adaptive CPU.
// These are only Used during a dumpsys to improve bug report quality.
class AdaptiveCpuStats {
public:
AdaptiveCpuStats() : mTimeSource(std::make_unique<TimeSource>()) {}
AdaptiveCpuStats(std::unique_ptr<ITimeSource> timeSource)
: mTimeSource(std::move(timeSource)) {}
void RegisterStartRun();
void RegisterSuccessfulRun(ThrottleDecision previousThrottleDecision,
ThrottleDecision throttleDecision,
WorkDurationFeatures workDurationFeatures,
const AdaptiveCpuConfig &config);
void DumpToStream(std::ostream &stream) const;
private:
const std::unique_ptr<ITimeSource> mTimeSource;
size_t mNumStartedRuns = 0;
size_t mNumSuccessfulRuns = 0;
std::chrono::nanoseconds mStartTime;
std::chrono::nanoseconds mLastRunStartTime;
std::chrono::nanoseconds mLastRunSuccessTime;
std::chrono::nanoseconds mTotalRunDuration;
std::map<ThrottleDecision, size_t> mNumThrottles;
std::map<ThrottleDecision, std::chrono::nanoseconds> mThrottleDurations;
std::map<ThrottleDecision, size_t> mNumDurations;
std::map<ThrottleDecision, size_t> mNumMissedDeadlines;
static std::string FormatDuration(std::chrono::nanoseconds duration);
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,149 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "CpuFrequencyReader.h"
#include <android-base/logging.h>
#include <inttypes.h>
#include <utils/Trace.h>
#include <fstream>
#include <memory>
#include <sstream>
using std::chrono_literals::operator""ms;
constexpr std::string_view kCpuPolicyDirectory("/sys/devices/system/cpu/cpufreq");
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
bool CpuFrequencyReader::Init() {
ATRACE_CALL();
mCpuPolicyIds.clear();
if (!ReadCpuPolicyIds(&mCpuPolicyIds)) {
return false;
}
mPreviousCpuPolicyFrequencies.clear();
return ReadCpuPolicyFrequencies(&mPreviousCpuPolicyFrequencies);
}
bool CpuFrequencyReader::GetRecentCpuPolicyFrequencies(
std::vector<CpuPolicyAverageFrequency> *result) {
ATRACE_CALL();
std::map<uint32_t, std::map<uint64_t, std::chrono::milliseconds>> cpuPolicyFrequencies;
if (!ReadCpuPolicyFrequencies(&cpuPolicyFrequencies)) {
return false;
}
for (const auto &[policyId, cpuFrequencies] : cpuPolicyFrequencies) {
const auto &previousCpuFrequencies = mPreviousCpuPolicyFrequencies.find(policyId);
if (previousCpuFrequencies == mPreviousCpuPolicyFrequencies.end()) {
LOG(ERROR) << "Couldn't find policy " << policyId << " in previous frequencies";
return false;
}
uint64_t weightedFrequenciesSumHz = 0;
std::chrono::milliseconds timeSum = 0ms;
for (const auto &[frequencyHz, time] : cpuFrequencies) {
const auto &previousCpuFrequency = previousCpuFrequencies->second.find(frequencyHz);
if (previousCpuFrequency == previousCpuFrequencies->second.end()) {
LOG(ERROR) << "Couldn't find frequency " << frequencyHz
<< " in previous frequencies";
return false;
}
const std::chrono::milliseconds recentTime = time - previousCpuFrequency->second;
weightedFrequenciesSumHz += frequencyHz * recentTime.count();
timeSum += recentTime;
}
const uint64_t averageFrequencyHz =
timeSum != 0ms ? weightedFrequenciesSumHz / timeSum.count() : 0;
result->push_back({.policyId = policyId, .averageFrequencyHz = averageFrequencyHz});
}
mPreviousCpuPolicyFrequencies = cpuPolicyFrequencies;
return true;
}
std::map<uint32_t, std::map<uint64_t, std::chrono::milliseconds>>
CpuFrequencyReader::GetPreviousCpuPolicyFrequencies() const {
return mPreviousCpuPolicyFrequencies;
}
bool CpuFrequencyReader::ReadCpuPolicyFrequencies(
std::map<uint32_t, std::map<uint64_t, std::chrono::milliseconds>> *result) {
ATRACE_CALL();
for (const uint32_t cpuPolicyId : mCpuPolicyIds) {
std::stringstream timeInStatePath;
timeInStatePath << "/sys/devices/system/cpu/cpufreq/policy" << cpuPolicyId
<< "/stats/time_in_state";
std::unique_ptr<std::istream> timeInStateFile;
if (!mFilesystem->ReadFileStream(timeInStatePath.str(), &timeInStateFile)) {
return false;
}
std::map<uint64_t, std::chrono::milliseconds> cpuFrequencies;
std::string timeInStateLine;
while (std::getline(*timeInStateFile, timeInStateLine)) {
// Time format in time_in_state is 10s of milliseconds:
// https://www.kernel.org/doc/Documentation/cpu-freq/cpufreq-stats.txt
uint64_t frequencyHz, time10Ms;
if (std::sscanf(timeInStateLine.c_str(), "%" PRIu64 " %" PRIu64 "\n", &frequencyHz,
&time10Ms) != 2) {
LOG(ERROR) << "Failed to parse time_in_state line: " << timeInStateLine;
return false;
}
cpuFrequencies[frequencyHz] = time10Ms * 10ms;
}
if (cpuFrequencies.size() > 500) {
LOG(ERROR) << "Found " << cpuFrequencies.size() << " frequencies for policy "
<< cpuPolicyId << ", aborting";
return false;
}
(*result)[cpuPolicyId] = cpuFrequencies;
}
return true;
}
bool CpuFrequencyReader::ReadCpuPolicyIds(std::vector<uint32_t> *result) const {
ATRACE_CALL();
std::vector<std::string> entries;
if (!mFilesystem->ListDirectory(kCpuPolicyDirectory.data(), &entries)) {
return false;
}
for (const auto &entry : entries) {
uint32_t cpuPolicyId;
if (!sscanf(entry.c_str(), "policy%d", &cpuPolicyId)) {
continue;
}
result->push_back(cpuPolicyId);
}
// Sort the list, so that getRecentCpuPolicyFrequencies always returns frequencies sorted by
// policy ID.
std::sort(result->begin(), result->end());
return true;
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,91 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <chrono>
#include <map>
#include <ostream>
#include <set>
#include <vector>
#include "IFilesystem.h"
#include "RealFilesystem.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
struct CpuPolicyAverageFrequency {
const uint32_t policyId;
const uint64_t averageFrequencyHz;
bool operator==(const CpuPolicyAverageFrequency &other) const {
return policyId == other.policyId && averageFrequencyHz == other.averageFrequencyHz;
}
};
class CpuFrequencyReader {
public:
CpuFrequencyReader() : mFilesystem(std::make_unique<RealFilesystem>()) {}
CpuFrequencyReader(std::unique_ptr<IFilesystem> filesystem)
: mFilesystem(std::move(filesystem)) {}
// Initialize reading, must be done before calling other methods.
// Work is not done in constructor as it accesses files.
// Returns true on success.
bool Init();
// Gets the average frequency each CPU policy was using, since this method was last called.
// Results are returned sorted by policyId.
// Returns true on success.
bool GetRecentCpuPolicyFrequencies(std::vector<CpuPolicyAverageFrequency> *result);
// The most recently read frequencies for each CPU policy. See readCpuPolicyFrequencies for type
// explanation. Used for dumping to bug reports.
std::map<uint32_t, std::map<uint64_t, std::chrono::milliseconds>>
GetPreviousCpuPolicyFrequencies() const;
private:
// CPU policy IDs read from /sys. Initialized in #init(). Sorted ascending.
std::vector<uint32_t> mCpuPolicyIds;
// The CPU frequencies when #getRecentCpuPolicyFrequencies was last called (or #init if it has
// not been called yet).
// See readCpuPolicyFrequencies for explanation of type.
std::map<uint32_t, std::map<uint64_t, std::chrono::milliseconds>> mPreviousCpuPolicyFrequencies;
const std::unique_ptr<IFilesystem> mFilesystem;
// Reads, from the /sys filesystem, the CPU frequencies used by each policy.
// - The outer map's key is the CPU policy ID.
// - The inner map's key is the CPU frequency in Hz.
// - The inner map's value is the time the policy has been running at that frequency, aggregated
// since boot.
// Returns true on success.
bool ReadCpuPolicyFrequencies(
std::map<uint32_t, std::map<uint64_t, std::chrono::milliseconds>> *result);
bool ReadCpuPolicyIds(std::vector<uint32_t> *result) const;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,132 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "CpuLoadReaderProcStat.h"
#include <android-base/logging.h>
#include <inttypes.h>
#include <utils/Trace.h>
#include <array>
#include <fstream>
#include <sstream>
#include <string>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
bool CpuLoadReaderProcStat::Init() {
mPreviousCpuTimes.clear();
return ReadCpuTimes(&mPreviousCpuTimes);
}
bool CpuLoadReaderProcStat::GetRecentCpuLoads(
std::array<double, NUM_CPU_CORES> *cpuCoreIdleTimesPercentage) {
ATRACE_CALL();
if (cpuCoreIdleTimesPercentage == nullptr) {
LOG(ERROR) << "Got nullptr output in getRecentCpuLoads";
return false;
}
std::map<uint32_t, CpuTime> cpuTimes;
if (!ReadCpuTimes(&cpuTimes)) {
return false;
}
if (cpuTimes.empty()) {
LOG(ERROR) << "Failed to find any CPU times";
return false;
}
for (const auto &[cpuId, cpuTime] : cpuTimes) {
const auto previousCpuTime = mPreviousCpuTimes.find(cpuId);
if (previousCpuTime == mPreviousCpuTimes.end()) {
LOG(ERROR) << "Couldn't find CPU " << cpuId << " in previous CPU times";
return false;
}
const auto recentIdleTimeMs = cpuTime.idleTimeMs - previousCpuTime->second.idleTimeMs;
const auto recentTotalTimeMs = cpuTime.totalTimeMs - previousCpuTime->second.totalTimeMs;
if (recentIdleTimeMs > recentTotalTimeMs) {
LOG(ERROR) << "Found more recent idle time than total time: idle=" << recentIdleTimeMs
<< ", total=" << recentTotalTimeMs;
return false;
}
const double idleTimePercentage =
static_cast<double>(recentIdleTimeMs) / (recentTotalTimeMs);
LOG(VERBOSE) << "Read CPU idle time: cpuId=" << cpuId
<< ", idleTimePercentage=" << idleTimePercentage;
(*cpuCoreIdleTimesPercentage)[cpuId] = idleTimePercentage;
}
mPreviousCpuTimes = cpuTimes;
return true;
}
bool CpuLoadReaderProcStat::ReadCpuTimes(std::map<uint32_t, CpuTime> *result) {
ATRACE_CALL();
std::unique_ptr<std::istream> file;
if (!mFilesystem->ReadFileStream("/proc/stat", &file)) {
return false;
}
std::string line;
ATRACE_BEGIN("loop");
while (std::getline(*file, line)) {
ATRACE_NAME("parse");
uint32_t cpuId;
// Times reported when the CPU is active.
uint64_t user, nice, system, irq, softIrq, steal, guest, guestNice;
// Times reported when the CPU is idle.
uint64_t idle, ioWait;
// Order & values taken from `fs/proc/stat.c`.
if (std::sscanf(line.c_str(),
"cpu%d %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64
" %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64 " ",
&cpuId, &user, &nice, &system, &idle, &ioWait, &irq, &softIrq, &steal,
&guest, &guestNice) != 11) {
continue;
}
uint64_t idleTimeJiffies = idle + ioWait;
uint64_t totalTimeJiffies =
user + nice + system + irq + softIrq + steal + guest + guestNice + idleTimeJiffies;
(*result)[cpuId] = {.idleTimeMs = JiffiesToMs(idleTimeJiffies),
.totalTimeMs = JiffiesToMs(totalTimeJiffies)};
}
ATRACE_END();
return true;
}
void CpuLoadReaderProcStat::DumpToStream(std::stringstream &stream) const {
stream << "CPU loads from /proc/stat:\n";
for (const auto &[cpuId, cpuTime] : mPreviousCpuTimes) {
stream << "- CPU=" << cpuId << ", idleTime=" << cpuTime.idleTimeMs
<< "ms, totalTime=" << cpuTime.totalTimeMs << "ms\n";
}
}
uint64_t CpuLoadReaderProcStat::JiffiesToMs(uint64_t jiffies) {
return (jiffies * 1000) / sysconf(_SC_CLK_TCK);
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,63 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <map>
#include "ICpuLoadReader.h"
#include "IFilesystem.h"
#include "RealFilesystem.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
struct CpuTime {
uint64_t idleTimeMs;
uint64_t totalTimeMs;
};
// Reads CPU idle stats from /proc/stat.
class CpuLoadReaderProcStat : public ICpuLoadReader {
public:
CpuLoadReaderProcStat() : mFilesystem(std::make_unique<RealFilesystem>()) {}
CpuLoadReaderProcStat(std::unique_ptr<IFilesystem> filesystem)
: mFilesystem(std::move(filesystem)) {}
bool Init() override;
bool GetRecentCpuLoads(std::array<double, NUM_CPU_CORES> *cpuCoreIdleTimesPercentage) override;
void DumpToStream(std::stringstream &stream) const override;
private:
std::map<uint32_t, CpuTime> mPreviousCpuTimes;
const std::unique_ptr<IFilesystem> mFilesystem;
bool ReadCpuTimes(std::map<uint32_t, CpuTime> *result);
// Converts jiffies to milliseconds. Jiffies is the granularity the kernel reports times in,
// including the timings in CPU statistics.
static uint64_t JiffiesToMs(uint64_t jiffies);
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,151 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "CpuLoadReaderSysDevices.h"
#include <android-base/logging.h>
#include <inttypes.h>
#include <utils/Trace.h>
#include <fstream>
#include <sstream>
#include <string>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
std::chrono::nanoseconds getKernelTime() {
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return std::chrono::nanoseconds(ts.tv_sec * 1000000000UL + ts.tv_nsec);
}
bool CpuLoadReaderSysDevices::Init() {
mIdleStateNames.clear();
if (!ReadIdleStateNames(&mIdleStateNames)) {
return false;
}
return ReadCpuTimes(&mPreviousCpuTimes);
}
bool CpuLoadReaderSysDevices::GetRecentCpuLoads(
std::array<double, NUM_CPU_CORES> *cpuCoreIdleTimesPercentage) {
ATRACE_CALL();
if (cpuCoreIdleTimesPercentage == nullptr) {
LOG(ERROR) << "Got nullptr output in getRecentCpuLoads";
return false;
}
std::array<CpuTime, NUM_CPU_CORES> cpuTimes;
if (!ReadCpuTimes(&cpuTimes)) {
return false;
}
if (cpuTimes.empty()) {
LOG(ERROR) << "Failed to find any CPU times";
return false;
}
for (size_t cpuId = 0; cpuId < NUM_CPU_CORES; cpuId++) {
const auto cpuTime = cpuTimes[cpuId];
const auto previousCpuTime = mPreviousCpuTimes[cpuId];
auto recentIdleTime = cpuTime.idleTime - previousCpuTime.idleTime;
const auto recentTotalTime = cpuTime.totalTime - previousCpuTime.totalTime;
if (recentIdleTime > recentTotalTime) {
// This happens occasionally, as we use the idle time from the kernel, and the current
// time from userspace.
recentIdleTime = recentTotalTime;
}
const double idleTimePercentage =
static_cast<double>(recentIdleTime.count()) / recentTotalTime.count();
(*cpuCoreIdleTimesPercentage)[cpuId] = idleTimePercentage;
}
mPreviousCpuTimes = cpuTimes;
return true;
}
void CpuLoadReaderSysDevices::DumpToStream(std::stringstream &stream) const {
stream << "CPU loads from /sys/devices/system/cpu/cpuN/cpuidle:\n";
for (size_t cpuId = 0; cpuId < NUM_CPU_CORES; cpuId++) {
stream << "- CPU=" << cpuId << ", idleTime=" << mPreviousCpuTimes[cpuId].idleTime.count()
<< "ms, totalTime=" << mPreviousCpuTimes[cpuId].totalTime.count() << "ms\n";
}
}
bool CpuLoadReaderSysDevices::ReadCpuTimes(std::array<CpuTime, NUM_CPU_CORES> *result) const {
ATRACE_CALL();
const auto totalTime = mTimeSource->GetTime();
for (size_t cpuId = 0; cpuId < NUM_CPU_CORES; cpuId++) {
std::chrono::microseconds idleTime;
for (const auto &idleStateName : mIdleStateNames) {
std::stringstream cpuIdlePath;
cpuIdlePath << "/sys/devices/system/cpu/"
<< "cpu" << cpuId << "/cpuidle/" << idleStateName << "/time";
std::unique_ptr<std::istream> file;
if (!mFilesystem->ReadFileStream(cpuIdlePath.str(), &file)) {
return false;
}
// Times are reported in microseconds:
// https://www.kernel.org/doc/Documentation/cpuidle/sysfs.txt
std::string idleTimeUs(std::istreambuf_iterator<char>(*file), {});
idleTime += std::chrono::microseconds(std::atoi(idleTimeUs.c_str()));
}
(*result)[cpuId] = {
.idleTime = idleTime,
.totalTime = std::chrono::duration_cast<std::chrono::microseconds>(totalTime),
};
}
return true;
}
bool CpuLoadReaderSysDevices::ReadIdleStateNames(std::vector<std::string> *result) const {
std::vector<std::string> idleStateNames;
if (!mFilesystem->ListDirectory("/sys/devices/system/cpu/cpu0/cpuidle", &idleStateNames)) {
return false;
}
for (const auto &idleStateName : idleStateNames) {
if (idleStateName.length() == 0 || idleStateName[0] == '.') {
continue;
}
std::vector<std::string> files;
if (!mFilesystem->ListDirectory(
std::string("/sys/devices/system/cpu/cpu0/cpuidle/") + idleStateName, &files)) {
return false;
}
if (std::find(files.begin(), files.end(), "time") == files.end()) {
continue;
}
result->push_back(idleStateName);
}
if (idleStateNames.empty()) {
LOG(ERROR) << "Found no idle state names";
return false;
}
return true;
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,71 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <chrono>
#include <map>
#include "ICpuLoadReader.h"
#include "IFilesystem.h"
#include "ITimeSource.h"
#include "Model.h"
#include "RealFilesystem.h"
#include "TimeSource.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
struct CpuTime {
std::chrono::microseconds idleTime;
std::chrono::microseconds totalTime;
};
// Reads CPU idle stats from /sys/devices/system/cpu/cpuN/cpuidle.
class CpuLoadReaderSysDevices : public ICpuLoadReader {
public:
CpuLoadReaderSysDevices()
: mFilesystem(std::make_unique<RealFilesystem>()),
mTimeSource(std::make_unique<TimeSource>()) {}
CpuLoadReaderSysDevices(std::unique_ptr<IFilesystem> filesystem,
std::unique_ptr<ITimeSource> timeSource)
: mFilesystem(std::move(filesystem)), mTimeSource(std::move(timeSource)) {}
bool Init() override;
bool GetRecentCpuLoads(std::array<double, NUM_CPU_CORES> *cpuCoreIdleTimesPercentage) override;
void DumpToStream(std::stringstream &stream) const override;
private:
const std::unique_ptr<IFilesystem> mFilesystem;
const std::unique_ptr<ITimeSource> mTimeSource;
std::array<CpuTime, NUM_CPU_CORES> mPreviousCpuTimes;
std::vector<std::string> mIdleStateNames;
bool ReadCpuTimes(std::array<CpuTime, NUM_CPU_CORES> *result) const;
bool ReadIdleStateNames(std::vector<std::string> *result) const;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-libperfmgr"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "Device.h"
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <utils/Trace.h>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
Device ReadDevice() {
ATRACE_CALL();
const std::string deviceProperty = ::android::base::GetProperty("ro.product.device", "");
Device device;
if (deviceProperty == "raven") {
device = Device::RAVEN;
} else if (deviceProperty == "oriole") {
device = Device::ORIOLE;
} else {
LOG(WARNING) << "Failed to parse device property, setting to UNKNOWN: " << deviceProperty;
device = Device::UNKNOWN;
}
LOG(DEBUG) << "Parsed device: deviceProperty=" << deviceProperty
<< ", device=" << static_cast<uint32_t>(device);
return device;
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,35 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#pragma once
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
enum class Device { UNKNOWN = 0, RAVEN = 1, ORIOLE = 2 };
Device ReadDevice();
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,49 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <array>
#include <sstream>
#include "Model.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
class ICpuLoadReader {
public:
// Initialize reading, must be done before calling other methods.
// Work is not done in constructor as it accesses files.
virtual bool Init() = 0;
// Get the load of each CPU, since the last time this method was called.
virtual bool GetRecentCpuLoads(
std::array<double, NUM_CPU_CORES> *cpuCoreIdleTimesPercentage) = 0;
// Dump internal state to a string stream. Used for dumpsys.
virtual void DumpToStream(std::stringstream &stream) const = 0;
virtual ~ICpuLoadReader() {}
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,49 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <chrono>
#include <memory>
#include <ostream>
#include <vector>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
// Abstracted so we can mock in tests.
class IFilesystem {
public:
virtual ~IFilesystem() {}
virtual bool ListDirectory(const std::string &path, std::vector<std::string> *result) const = 0;
virtual bool ReadFileStream(const std::string &path,
std::unique_ptr<std::istream> *result) const = 0;
// Resets the file stream, so that the next read will read from the beginning.
// This function exists in IFilesystem rather than using istream::seekg directly. This is
// so we can mock this function in tests, allowing us to return different data on reset.
virtual bool ResetFileStream(const std::unique_ptr<std::istream> &fileStream) const = 0;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,41 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <chrono>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
// Abstracted so we can mock in tests.
class ITimeSource {
public:
virtual ~ITimeSource() {}
virtual std::chrono::nanoseconds GetTime() const = 0;
virtual std::chrono::nanoseconds GetKernelTime() const = 0;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,135 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "KernelCpuFeatureReader.h"
#include <android-base/logging.h>
#include <utils/Trace.h>
#include <ostream>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
constexpr std::string_view kKernelFilePath("/proc/vendor_sched/acpu_stats");
constexpr size_t kReadBufferSize = sizeof(acpu_stats) * NUM_CPU_CORES;
bool KernelCpuFeatureReader::Init() {
ATRACE_CALL();
if (!OpenStatsFile(&mStatsFile)) {
return false;
}
return ReadStats(&mPreviousStats, &mPreviousReadTime);
}
bool KernelCpuFeatureReader::GetRecentCpuFeatures(
std::array<double, NUM_CPU_POLICIES> *cpuPolicyAverageFrequencyHz,
std::array<double, NUM_CPU_CORES> *cpuCoreIdleTimesPercentage) {
ATRACE_CALL();
std::array<acpu_stats, NUM_CPU_CORES> stats;
std::chrono::nanoseconds readTime;
if (!ReadStats(&stats, &readTime)) {
return false;
}
const std::chrono::nanoseconds timeDelta = readTime - mPreviousReadTime;
for (size_t i = 0; i < NUM_CPU_POLICIES; i++) {
// acpu_stats has data per-CPU, but frequency data is equivalent for all CPUs in a policy.
// So, we only read the first CPU in each policy.
const size_t statsIdx = CPU_POLICY_INDICES[i];
if (stats[statsIdx].weighted_sum_freq < mPreviousStats[statsIdx].weighted_sum_freq) {
LOG(WARNING) << "New weighted_sum_freq is less than old: new="
<< stats[statsIdx].weighted_sum_freq
<< ", old=" << mPreviousStats[statsIdx].weighted_sum_freq;
mPreviousStats[statsIdx].weighted_sum_freq = stats[statsIdx].weighted_sum_freq;
}
(*cpuPolicyAverageFrequencyHz)[i] =
static_cast<double>(stats[statsIdx].weighted_sum_freq -
mPreviousStats[statsIdx].weighted_sum_freq) /
timeDelta.count();
}
for (size_t i = 0; i < NUM_CPU_CORES; i++) {
if (stats[i].total_idle_time_ns < mPreviousStats[i].total_idle_time_ns) {
LOG(WARNING) << "New total_idle_time_ns is less than old: new="
<< stats[i].total_idle_time_ns
<< ", old=" << mPreviousStats[i].total_idle_time_ns;
mPreviousStats[i].total_idle_time_ns = stats[i].total_idle_time_ns;
}
(*cpuCoreIdleTimesPercentage)[i] =
static_cast<double>(stats[i].total_idle_time_ns -
mPreviousStats[i].total_idle_time_ns) /
timeDelta.count();
}
mPreviousStats = stats;
mPreviousReadTime = readTime;
return true;
}
bool KernelCpuFeatureReader::OpenStatsFile(std::unique_ptr<std::istream> *file) {
ATRACE_CALL();
return mFilesystem->ReadFileStream(kKernelFilePath.data(), file);
}
bool KernelCpuFeatureReader::ReadStats(std::array<acpu_stats, NUM_CPU_CORES> *stats,
std::chrono::nanoseconds *readTime) {
ATRACE_CALL();
*readTime = mTimeSource->GetKernelTime();
if (!mFilesystem->ResetFileStream(mStatsFile)) {
return false;
}
char buffer[kReadBufferSize];
{
ATRACE_NAME("read");
if (!mStatsFile->read(buffer, kReadBufferSize).good()) {
LOG(ERROR) << "Failed to read stats file";
return false;
}
}
const size_t bytesRead = mStatsFile->gcount();
if (bytesRead != kReadBufferSize) {
LOG(ERROR) << "Didn't read full data: expected=" << kReadBufferSize
<< ", actual=" << bytesRead;
return false;
}
const auto kernelStructs = reinterpret_cast<acpu_stats *>(buffer);
std::copy(kernelStructs, kernelStructs + NUM_CPU_CORES, stats->begin());
return true;
}
void KernelCpuFeatureReader::DumpToStream(std::ostream &stream) const {
ATRACE_CALL();
stream << "CPU features from acpu_stats:\n";
for (size_t i = 0; i < NUM_CPU_CORES; i++) {
stream << "- CPU " << i << ": weighted_sum_freq=" << mPreviousStats[i].weighted_sum_freq
<< ", total_idle_time_ns=" << mPreviousStats[i].total_idle_time_ns << "\n";
}
stream << "- Last read time: " << mPreviousReadTime.count() << "ns\n";
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,83 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#pragma once
#include <array>
#include <ostream>
#include "IFilesystem.h"
#include "ITimeSource.h"
#include "Model.h"
#include "RealFilesystem.h"
#include "TimeSource.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
// Kernel <-> Userspace ABI for CPU features. See kernel/sched/acpu.c.
// Contains CPU statistics for a single CPU. The kernel reports an `acpu_stats` struct for each CPU
// on the system.
struct acpu_stats {
// Sum of the CPU frequencies that the CPU used, multiplied by how much time was spent in each
// frequency. Measured in ns*KHz. E.g.:
// 10ns at 100MHz, 2ns at 50MHz = 10*100,000 + 2*50,000 = 1,100,000
// This is used to calculate the average frequency the CPU was running at between two times:
// (new.weighted_sum_freq - old.weighted_sum_freq) / elapsed_time_ns
uint64_t weighted_sum_freq;
// The total time (in nanoseconds) that the CPU was idle.
// This is ued to calculate the percent of time the CPU was idle between two times:
// (new.total_idle_time_ns - old.total_idle_time_ns) / elapsed_time_ns
uint64_t total_idle_time_ns;
};
class KernelCpuFeatureReader {
public:
KernelCpuFeatureReader()
: mFilesystem(std::make_unique<RealFilesystem>()),
mTimeSource(std::make_unique<TimeSource>()) {}
KernelCpuFeatureReader(std::unique_ptr<IFilesystem> filesystem,
std::unique_ptr<ITimeSource> timeSource)
: mFilesystem(std::move(filesystem)), mTimeSource(std::move(timeSource)) {}
bool Init();
bool GetRecentCpuFeatures(std::array<double, NUM_CPU_POLICIES> *cpuPolicyAverageFrequencyHz,
std::array<double, NUM_CPU_CORES> *cpuCoreIdleTimesPercentage);
void DumpToStream(std::ostream &stream) const;
private:
const std::unique_ptr<IFilesystem> mFilesystem;
const std::unique_ptr<ITimeSource> mTimeSource;
// We only open the stats file once and reuse the file descriptor. We find this reduces
// ReadStats runtime by 2x.
std::unique_ptr<std::istream> mStatsFile;
std::array<acpu_stats, NUM_CPU_CORES> mPreviousStats;
std::chrono::nanoseconds mPreviousReadTime;
bool OpenStatsFile(std::unique_ptr<std::istream> *file);
bool ReadStats(std::array<acpu_stats, NUM_CPU_CORES> *stats,
std::chrono::nanoseconds *readTime);
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,106 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "Model.h"
#include <android-base/logging.h>
#include <utils/Trace.h>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
bool ModelInput::SetCpuFreqiencies(
const std::vector<CpuPolicyAverageFrequency> &cpuPolicyAverageFrequencies) {
ATRACE_CALL();
if (cpuPolicyAverageFrequencies.size() != cpuPolicyAverageFrequencyHz.size()) {
LOG(ERROR) << "Received incorrect amount of CPU policy frequencies, expected "
<< cpuPolicyAverageFrequencyHz.size() << ", received "
<< cpuPolicyAverageFrequencies.size();
return false;
}
int32_t previousPolicyId = -1;
for (uint32_t i = 0; i < cpuPolicyAverageFrequencies.size(); i++) {
if (previousPolicyId >= static_cast<int32_t>(cpuPolicyAverageFrequencies[i].policyId)) {
LOG(ERROR) << "CPU frequencies weren't sorted by policy ID, found " << previousPolicyId
<< " " << cpuPolicyAverageFrequencies[i].policyId;
return false;
}
previousPolicyId = cpuPolicyAverageFrequencies[i].policyId;
cpuPolicyAverageFrequencyHz[i] = cpuPolicyAverageFrequencies[i].averageFrequencyHz;
}
return true;
}
void ModelInput::LogToAtrace() const {
if (!ATRACE_ENABLED()) {
return;
}
ATRACE_CALL();
for (int i = 0; i < cpuPolicyAverageFrequencyHz.size(); i++) {
ATRACE_INT((std::string("ModelInput_frequency_") + std::to_string(i)).c_str(),
static_cast<int>(cpuPolicyAverageFrequencyHz[i]));
}
for (int i = 0; i < cpuCoreIdleTimesPercentage.size(); i++) {
ATRACE_INT((std::string("ModelInput_idle_") + std::to_string(i)).c_str(),
static_cast<int>(cpuCoreIdleTimesPercentage[i] * 100));
}
ATRACE_INT("ModelInput_workDurations_averageDurationNs",
workDurationFeatures.averageDuration.count());
ATRACE_INT("ModelInput_workDurations_maxDurationNs", workDurationFeatures.maxDuration.count());
ATRACE_INT("ModelInput_workDurations_numMissedDeadlines",
workDurationFeatures.numMissedDeadlines);
ATRACE_INT("ModelInput_workDurations_numDurations", workDurationFeatures.numDurations);
ATRACE_INT("ModelInput_prevThrottle", (int)previousThrottleDecision);
ATRACE_INT("ModelInput_device", static_cast<int>(device));
}
ThrottleDecision Model::Run(const std::deque<ModelInput> &modelInputs,
const AdaptiveCpuConfig &config) {
ATRACE_CALL();
if (config.randomThrottleDecisionProbability > 0 &&
mShouldRandomThrottleDistribution(mGenerator) < config.randomThrottleDecisionProbability) {
std::uniform_int_distribution<uint32_t> optionDistribution(
0, config.randomThrottleOptions.size() - 1);
const ThrottleDecision throttleDecision =
config.randomThrottleOptions[optionDistribution(mGenerator)];
LOG(VERBOSE) << "Randomly overrided throttle decision: "
<< static_cast<uint32_t>(throttleDecision);
ATRACE_INT("AdaptiveCpu_randomThrottleDecision", static_cast<uint32_t>(throttleDecision));
return throttleDecision;
}
ATRACE_INT("AdaptiveCpu_randomThrottleDecision", -1);
return RunDecisionTree(modelInputs);
}
ThrottleDecision Model::RunDecisionTree(const std::deque<ModelInput> &modelInputs
__attribute__((unused))) {
ATRACE_CALL();
#include "models/model.inc"
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,88 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#pragma once
#include <inttypes.h>
#include <array>
#include <chrono>
#include <deque>
#include <random>
#include <vector>
#include "AdaptiveCpuConfig.h"
#include "CpuFrequencyReader.h"
#include "Device.h"
#include "ThrottleDecision.h"
#include "WorkDurationProcessor.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
// Currently Adaptive CPU is targeted to only raven/oriole, so we can hardcode the CPU architecture.
// If we extend to other architectures, this will have to vary per-device or be dynamically loaded.
constexpr uint32_t NUM_CPU_CORES = 8;
constexpr uint32_t NUM_CPU_POLICIES = 3;
constexpr std::array<uint32_t, NUM_CPU_POLICIES> CPU_POLICY_INDICES{0, 4, 6};
struct ModelInput {
std::array<double, NUM_CPU_POLICIES> cpuPolicyAverageFrequencyHz;
std::array<double, NUM_CPU_CORES> cpuCoreIdleTimesPercentage;
WorkDurationFeatures workDurationFeatures;
ThrottleDecision previousThrottleDecision;
Device device;
bool SetCpuFreqiencies(
const std::vector<CpuPolicyAverageFrequency> &cpuPolicyAverageFrequencies);
void LogToAtrace() const;
bool operator==(const ModelInput &other) const {
return cpuPolicyAverageFrequencyHz == other.cpuPolicyAverageFrequencyHz &&
cpuCoreIdleTimesPercentage == other.cpuCoreIdleTimesPercentage &&
workDurationFeatures == other.workDurationFeatures &&
previousThrottleDecision == other.previousThrottleDecision;
}
};
class Model {
public:
Model()
: mShouldRandomThrottleDistribution(0, 1),
mRandomThrottleDistribution(static_cast<uint32_t>(ThrottleDecision::FIRST),
static_cast<uint32_t>(ThrottleDecision::LAST)) {}
ThrottleDecision Run(const std::deque<ModelInput> &modelInputs,
const AdaptiveCpuConfig &config);
private:
std::default_random_engine mGenerator;
std::uniform_real_distribution<double> mShouldRandomThrottleDistribution;
std::uniform_int_distribution<uint32_t> mRandomThrottleDistribution;
ThrottleDecision RunDecisionTree(const std::deque<ModelInput> &modelInputs);
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,76 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "RealFilesystem.h"
#include <android-base/logging.h>
#include <dirent.h>
#include <utils/Trace.h>
#include <fstream>
#include <istream>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
bool RealFilesystem::ListDirectory(const std::string &path,
std::vector<std::string> *result) const {
ATRACE_CALL();
// We can't use std::filesystem, see aosp/894015 & b/175635923.
auto dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir(path.c_str()), closedir};
if (!dir) {
LOG(ERROR) << "Failed to open directory " << path;
return false;
}
dirent *entry;
while ((entry = readdir(&*dir)) != nullptr) {
result->emplace_back(entry->d_name);
}
return true;
}
bool RealFilesystem::ReadFileStream(const std::string &path,
std::unique_ptr<std::istream> *result) const {
ATRACE_CALL();
*result = std::make_unique<std::ifstream>(path);
if ((*result)->fail()) {
LOG(ERROR) << "Failed to read file stream: " << path;
return false;
}
return true;
}
bool RealFilesystem::ResetFileStream(const std::unique_ptr<std::istream> &fileStream) const {
if (fileStream->seekg(0).bad()) {
LOG(ERROR) << "Failed to reset file stream";
return false;
}
return true;
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,46 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <memory>
#include <ostream>
#include <vector>
#include "IFilesystem.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
class RealFilesystem : public IFilesystem {
public:
virtual ~RealFilesystem() {}
bool ListDirectory(const std::string &path, std::vector<std::string> *result) const override;
bool ReadFileStream(const std::string &path,
std::unique_ptr<std::istream> *result) const override;
bool ResetFileStream(const std::unique_ptr<std::istream> &fileStream) const override;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#include "ThrottleDecision.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
std::string ThrottleString(ThrottleDecision throttleDecision) {
switch (throttleDecision) {
case ThrottleDecision::NO_THROTTLE:
return "NO_THROTTLE";
case ThrottleDecision::THROTTLE_60:
return "THROTTLE_60";
case ThrottleDecision::THROTTLE_70:
return "THROTTLE_70";
case ThrottleDecision::THROTTLE_80:
return "THROTTLE_80";
case ThrottleDecision::THROTTLE_90:
return "THROTTLE_90";
default:
return "unknown";
}
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,62 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#pragma once
#include <string>
#include <unordered_map>
#include <vector>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
enum class ThrottleDecision {
NO_THROTTLE = 0,
THROTTLE_50 = 1,
THROTTLE_60 = 2,
THROTTLE_70 = 3,
THROTTLE_80 = 4,
THROTTLE_90 = 5,
FIRST = NO_THROTTLE,
LAST = THROTTLE_90,
};
std::string ThrottleString(ThrottleDecision throttleDecision);
static const std::unordered_map<ThrottleDecision, std::vector<std::string>>
THROTTLE_DECISION_TO_HINT_NAMES = {
{ThrottleDecision::NO_THROTTLE, {}},
{ThrottleDecision::THROTTLE_50,
{"LOW_POWER_LITTLE_CLUSTER_50", "LOW_POWER_MID_CLUSTER_50", "LOW_POWER_CPU_50"}},
{ThrottleDecision::THROTTLE_60,
{"LOW_POWER_LITTLE_CLUSTER_60", "LOW_POWER_MID_CLUSTER_60", "LOW_POWER_CPU_60"}},
{ThrottleDecision::THROTTLE_70,
{"LOW_POWER_LITTLE_CLUSTER_70", "LOW_POWER_MID_CLUSTER_70", "LOW_POWER_CPU_70"}},
{ThrottleDecision::THROTTLE_80,
{"LOW_POWER_LITTLE_CLUSTER_80", "LOW_POWER_MID_CLUSTER_80", "LOW_POWER_CPU_80"}},
{ThrottleDecision::THROTTLE_90,
{"LOW_POWER_LITTLE_CLUSTER_90", "LOW_POWER_MID_CLUSTER_90", "LOW_POWER_CPU_90"}}};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "TimeSource.h"
#include <utils/Trace.h>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
std::chrono::nanoseconds TimeSource::GetTime() const {
ATRACE_CALL();
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::system_clock::now().time_since_epoch());
}
std::chrono::nanoseconds TimeSource::GetKernelTime() const {
ATRACE_CALL();
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return std::chrono::nanoseconds(ts.tv_sec * 1000000000UL + ts.tv_nsec);
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,40 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include "ITimeSource.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
class TimeSource : public ITimeSource {
public:
~TimeSource() override {}
std::chrono::nanoseconds GetTime() const override;
std::chrono::nanoseconds GetKernelTime() const override;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,120 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-adaptivecpu"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "WorkDurationProcessor.h"
#include <android-base/logging.h>
#include <utils/Trace.h>
using std::chrono_literals::operator""ms;
using std::chrono_literals::operator""ns;
// The standard target duration, based on 60 FPS. Durations submitted with different targets are
// normalized against this target. For example, a duration that was at 80% of its target will be
// scaled to 0.8 * kNormalTargetDuration.
constexpr std::chrono::nanoseconds kNormalTargetDuration = 16666666ns;
// All durations shorter than this are ignored.
constexpr std::chrono::nanoseconds kMinDuration = 0ns;
// All durations longer than this are ignored.
constexpr std::chrono::nanoseconds kMaxDuration = 600 * kNormalTargetDuration;
// If we haven't processed a lot of batches, stop accepting new ones. In cases where the processing
// thread has crashed, but the reporting thread is still reporting, this prevents consuming large
// amounts of memory.
// TODO(b/213160386): Move to AdaptiveCpuConfig.
constexpr size_t kMaxUnprocessedBatches = 1000;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
bool WorkDurationProcessor::ReportWorkDurations(const std::vector<WorkDuration> &workDurations,
std::chrono::nanoseconds targetDuration) {
ATRACE_CALL();
LOG(VERBOSE) << "Received " << workDurations.size() << " work durations with target "
<< targetDuration.count() << "ns";
std::unique_lock<std::mutex> lock(mMutex);
if (mWorkDurationBatches.size() >= kMaxUnprocessedBatches) {
LOG(ERROR) << "Adaptive CPU isn't processing work durations fast enough";
mWorkDurationBatches.clear();
return false;
}
mWorkDurationBatches.emplace_back(workDurations, targetDuration);
return true;
}
WorkDurationFeatures WorkDurationProcessor::GetFeatures() {
ATRACE_CALL();
std::vector<WorkDurationBatch> workDurationBatches;
{
ATRACE_NAME("lock");
std::unique_lock<std::mutex> lock(mMutex);
mWorkDurationBatches.swap(workDurationBatches);
}
std::chrono::nanoseconds durationsSum = 0ns;
std::chrono::nanoseconds maxDuration = 0ns;
uint32_t numMissedDeadlines = 0;
uint32_t numDurations = 0;
for (const WorkDurationBatch &batch : workDurationBatches) {
for (const WorkDuration workDuration : batch.workDurations) {
std::chrono::nanoseconds duration(workDuration.durationNanos);
if (duration < kMinDuration || duration > kMaxDuration) {
continue;
}
// Normalise the duration and add it to the total.
// kMaxDuration * kStandardTarget.count() fits comfortably within int64_t.
std::chrono::nanoseconds durationNormalized =
(duration * kNormalTargetDuration.count()) / batch.targetDuration.count();
durationsSum += durationNormalized;
maxDuration = std::max(maxDuration, durationNormalized);
if (duration > batch.targetDuration) {
++numMissedDeadlines;
}
++numDurations;
}
}
std::chrono::nanoseconds averageDuration = durationsSum / numDurations;
return {
.averageDuration = averageDuration,
.maxDuration = maxDuration,
.numMissedDeadlines = numMissedDeadlines,
.numDurations = numDurations,
};
}
bool WorkDurationProcessor::HasWorkDurations() {
std::unique_lock<std::mutex> lock(mMutex);
return !mWorkDurationBatches.empty();
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,76 @@
#pragma once
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <aidl/android/hardware/power/WorkDuration.h>
#include <chrono>
#include <vector>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
using ::aidl::android::hardware::power::WorkDuration;
struct WorkDurationBatch {
WorkDurationBatch(const std::vector<WorkDuration> &workDurations,
std::chrono::nanoseconds targetDuration)
: workDurations(workDurations), targetDuration(targetDuration) {}
const std::vector<WorkDuration> workDurations;
const std::chrono::nanoseconds targetDuration;
};
struct WorkDurationFeatures {
std::chrono::nanoseconds averageDuration;
std::chrono::nanoseconds maxDuration;
uint32_t numMissedDeadlines;
uint32_t numDurations;
bool operator==(const WorkDurationFeatures &other) const {
return averageDuration == other.averageDuration && maxDuration == other.maxDuration &&
numMissedDeadlines == other.numMissedDeadlines && numDurations == other.numDurations;
}
};
class WorkDurationProcessor {
public:
bool ReportWorkDurations(const std::vector<WorkDuration> &workDurations,
std::chrono::nanoseconds targetDuration);
WorkDurationFeatures GetFeatures();
// True if ReportWorkDurations has been called since GetFeatures was last called.
bool HasWorkDurations();
private:
// The work durations reported since GetFeatures() was last called.
// Ordered from least recent to most recent.
std::vector<WorkDurationBatch> mWorkDurationBatches;
// Guards reading/writing mWorkDurationBatches.
std::mutex mMutex;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1 @@
exclude_files=.*

View file

@ -0,0 +1,4 @@
benm@google.com
miloslav@google.com
mishaw@google.com
silviavinyes@google.com

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,131 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <android-base/properties.h>
#include <gtest/gtest.h>
#include "adaptivecpu/AdaptiveCpuConfig.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
using std::chrono_literals::operator""ms;
using std::chrono_literals::operator""min;
class AdaptiveCpuConfigTest : public ::testing::Test {
protected:
void SetUp() override {
android::base::SetProperty("debug.adaptivecpu.iteration_sleep_duration_ms", "");
android::base::SetProperty("debug.adaptivecpu.hint_timeout_ms", "");
android::base::SetProperty("debug.adaptivecpu.random_throttle_decision_percent", "");
android::base::SetProperty("debug.adaptivecpu.random_throttle_options", "");
android::base::SetProperty("debug.adaptivecpu.enabled_hint_timeout_ms", "");
}
};
TEST(AdaptiveCpuConfigTest, valid) {
android::base::SetProperty("debug.adaptivecpu.iteration_sleep_duration_ms", "25");
android::base::SetProperty("debug.adaptivecpu.hint_timeout_ms", "500");
android::base::SetProperty("debug.adaptivecpu.random_throttle_decision_percent", "25");
android::base::SetProperty("debug.adaptivecpu.random_throttle_options", "0,3,4");
android::base::SetProperty("debug.adaptivecpu.enabled_hint_timeout_ms", "1000");
const AdaptiveCpuConfig expectedConfig{
.iterationSleepDuration = 25ms,
.hintTimeout = 500ms,
.randomThrottleDecisionProbability = 0.25,
.enabledHintTimeout = 1000ms,
.randomThrottleOptions = {ThrottleDecision::NO_THROTTLE, ThrottleDecision::THROTTLE_70,
ThrottleDecision::THROTTLE_80},
};
AdaptiveCpuConfig actualConfig;
ASSERT_TRUE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
ASSERT_EQ(actualConfig, expectedConfig);
}
TEST(AdaptiveCpuConfigTest, defaultConfig) {
android::base::SetProperty("debug.adaptivecpu.iteration_sleep_duration_ms", "");
android::base::SetProperty("debug.adaptivecpu.hint_timeout_ms", "");
android::base::SetProperty("debug.adaptivecpu.random_throttle_decision_percent", "");
android::base::SetProperty("debug.adaptivecpu.random_throttle_options", "");
android::base::SetProperty("debug.adaptivecpu.enabled_hint_timeout_ms", "");
AdaptiveCpuConfig actualConfig;
ASSERT_TRUE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
ASSERT_EQ(actualConfig, AdaptiveCpuConfig::DEFAULT);
}
TEST(AdaptiveCpuConfigTest, iterationSleepDuration_belowMin) {
android::base::SetProperty("debug.adaptivecpu.iteration_sleep_duration_ms", "2");
AdaptiveCpuConfig actualConfig;
ASSERT_TRUE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
ASSERT_EQ(actualConfig.iterationSleepDuration, 20ms);
}
TEST(AdaptiveCpuConfigTest, iterationSleepDuration_negative) {
android::base::SetProperty("debug.adaptivecpu.iteration_sleep_duration_ms", "-100");
AdaptiveCpuConfig actualConfig;
ASSERT_TRUE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
ASSERT_EQ(actualConfig.iterationSleepDuration, 1000ms);
}
TEST(AdaptiveCpuConfigTest, randomThrottleDecisionProbability_float) {
android::base::SetProperty("debug.adaptivecpu.random_throttle_decision_percent", "0.5");
AdaptiveCpuConfig actualConfig;
ASSERT_TRUE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
ASSERT_EQ(actualConfig.randomThrottleDecisionProbability, 0);
}
TEST(AdaptiveCpuConfigTest, randomThrottleDecisionProbability_tooBig) {
android::base::SetProperty("debug.adaptivecpu.random_throttle_decision_percent", "101");
AdaptiveCpuConfig actualConfig;
ASSERT_FALSE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
}
TEST(AdaptiveCpuConfigTest, randomThrottleOptions_invalidThrottle) {
android::base::SetProperty("debug.adaptivecpu.random_throttle_options", "0,1,2,9");
AdaptiveCpuConfig actualConfig;
ASSERT_FALSE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
}
TEST(AdaptiveCpuConfigTest, randomThrottleOptions_wrongDelim) {
android::base::SetProperty("debug.adaptivecpu.random_throttle_options", "0,1.2,3");
AdaptiveCpuConfig actualConfig;
ASSERT_FALSE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
}
TEST(AdaptiveCpuConfigTest, randomThrottleOptions_wrongNumber) {
android::base::SetProperty("debug.adaptivecpu.random_throttle_options", "0,1,2a,3");
AdaptiveCpuConfig actualConfig;
ASSERT_FALSE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
}
TEST(AdaptiveCpuConfigTest, randomThrottleOptions_straySpace) {
android::base::SetProperty("debug.adaptivecpu.random_throttle_options", "0,1 ,2,3");
AdaptiveCpuConfig actualConfig;
ASSERT_FALSE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
android::base::SetProperty("debug.adaptivecpu.random_throttle_options", "0,1,2,3 ");
ASSERT_FALSE(AdaptiveCpuConfig::ReadFromSystemProperties(&actualConfig));
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,129 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <gtest/gtest.h>
#include "adaptivecpu/AdaptiveCpuStats.h"
#include "mocks.h"
using testing::HasSubstr;
using testing::Return;
using std::chrono_literals::operator""ns;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
TEST(AdaptiveCpuStatsTest, singleRun) {
std::unique_ptr<MockTimeSource> timeSource = std::make_unique<MockTimeSource>();
EXPECT_CALL(*timeSource, GetTime())
.Times(3)
.WillOnce(Return(1000ns))
.WillOnce(Return(1100ns))
.WillOnce(Return(1200ns));
AdaptiveCpuStats stats(std::move(timeSource));
stats.RegisterStartRun();
stats.RegisterSuccessfulRun(ThrottleDecision::NO_THROTTLE, ThrottleDecision::THROTTLE_60, {},
AdaptiveCpuConfig::DEFAULT);
std::stringstream stream;
stats.DumpToStream(stream);
EXPECT_THAT(stream.str(), HasSubstr("- Successful runs / total runs: 1 / 1\n"));
EXPECT_THAT(stream.str(), HasSubstr("- Total run duration: 100.000000ns\n"));
EXPECT_THAT(stream.str(), HasSubstr("- Average run duration: 100.000000ns\n"));
EXPECT_THAT(stream.str(), HasSubstr("- Running time fraction: 0.5\n"));
EXPECT_THAT(stream.str(), HasSubstr("- THROTTLE_60: 1\n"));
}
TEST(AdaptiveCpuStatsTest, multipleRuns) {
std::unique_ptr<MockTimeSource> timeSource = std::make_unique<MockTimeSource>();
EXPECT_CALL(*timeSource, GetTime())
.Times(9)
.WillOnce(Return(1000ns)) // start #1
.WillOnce(Return(1100ns)) // success #1
.WillOnce(Return(2000ns)) // start #2
.WillOnce(Return(2200ns)) // success #2
.WillOnce(Return(3000ns)) // start #3
.WillOnce(Return(3100ns)) // success #3
.WillOnce(Return(4000ns)) // start #4
.WillOnce(Return(4800ns)) // success #4
.WillOnce(Return(5000ns)); // dump
AdaptiveCpuStats stats(std::move(timeSource));
stats.RegisterStartRun();
stats.RegisterSuccessfulRun(ThrottleDecision::NO_THROTTLE, ThrottleDecision::THROTTLE_60,
// Ignored, as this is the first call.
{.numDurations = 100000, .numMissedDeadlines = 123},
AdaptiveCpuConfig::DEFAULT);
stats.RegisterStartRun();
stats.RegisterSuccessfulRun(ThrottleDecision::THROTTLE_60, ThrottleDecision::THROTTLE_70,
{.numDurations = 100, .numMissedDeadlines = 10},
AdaptiveCpuConfig::DEFAULT);
stats.RegisterStartRun();
stats.RegisterSuccessfulRun(ThrottleDecision::THROTTLE_70, ThrottleDecision::THROTTLE_60,
{.numDurations = 50, .numMissedDeadlines = 1},
AdaptiveCpuConfig::DEFAULT);
stats.RegisterStartRun();
stats.RegisterSuccessfulRun(ThrottleDecision::THROTTLE_60, ThrottleDecision::THROTTLE_80,
{.numDurations = 200, .numMissedDeadlines = 20},
AdaptiveCpuConfig::DEFAULT);
std::stringstream stream;
stats.DumpToStream(stream);
EXPECT_THAT(stream.str(), HasSubstr("- Successful runs / total runs: 4 / 4\n"));
EXPECT_THAT(stream.str(), HasSubstr("- Total run duration: 1.200000us\n"));
EXPECT_THAT(stream.str(), HasSubstr("- Average run duration: 300.000000ns\n"));
EXPECT_THAT(stream.str(), HasSubstr("- Running time fraction: 0.3\n"));
EXPECT_THAT(stream.str(), HasSubstr("- THROTTLE_60: 2\n"));
EXPECT_THAT(stream.str(), HasSubstr("- THROTTLE_70: 1\n"));
EXPECT_THAT(stream.str(), HasSubstr("- THROTTLE_60: 30 / 300 (0.1)\n"));
EXPECT_THAT(stream.str(), HasSubstr("- THROTTLE_70: 1 / 50 (0.02)\n"));
}
TEST(AdaptiveCpuStatsTest, failedRun) {
std::unique_ptr<MockTimeSource> timeSource = std::make_unique<MockTimeSource>();
EXPECT_CALL(*timeSource, GetTime())
.Times(4)
.WillOnce(Return(1000ns))
.WillOnce(Return(1100ns))
.WillOnce(Return(1200ns))
.WillOnce(Return(1300ns));
AdaptiveCpuStats stats(std::move(timeSource));
stats.RegisterStartRun();
stats.RegisterStartRun();
stats.RegisterSuccessfulRun(ThrottleDecision::NO_THROTTLE, ThrottleDecision::THROTTLE_60, {},
AdaptiveCpuConfig::DEFAULT);
std::stringstream stream;
stats.DumpToStream(stream);
EXPECT_THAT(stream.str(), HasSubstr("- Successful runs / total runs: 1 / 2\n"));
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,159 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <gtest/gtest.h>
#include "adaptivecpu/CpuFrequencyReader.h"
#include "mocks.h"
using testing::_;
using testing::ByMove;
using testing::Return;
using std::chrono_literals::operator""ms;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
std::ostream &operator<<(std::ostream &stream, const CpuPolicyAverageFrequency &frequency) {
return stream << "CpuPolicyAverageFrequency(" << frequency.policyId << ", "
<< frequency.averageFrequencyHz << ")";
}
TEST(CpuFrequencyReaderTest, cpuPolicyIds) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
EXPECT_CALL(*filesystem, ListDirectory("/sys/devices/system/cpu/cpufreq", _))
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::vector<std::string>{"ignored1", "policy1", "ignored2",
"policy5", "policy10", "policybad"};
return true;
});
EXPECT_CALL(*filesystem, ReadFileStream(_, _))
.WillRepeatedly([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1 2\n3 4\n");
return true;
});
CpuFrequencyReader reader(std::move(filesystem));
EXPECT_TRUE(reader.Init());
std::map<uint32_t, std::map<uint64_t, std::chrono::milliseconds>> expected = {
{1, {{1, 20ms}, {3, 40ms}}}, {5, {{1, 20ms}, {3, 40ms}}}, {10, {{1, 20ms}, {3, 40ms}}}};
EXPECT_EQ(reader.GetPreviousCpuPolicyFrequencies(), expected);
}
TEST(CpuFrequencyReaderTest, getRecentCpuPolicyFrequencies) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
EXPECT_CALL(*filesystem, ListDirectory("/sys/devices/system/cpu/cpufreq", _))
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::vector<std::string>{"policy1", "policy2"};
return true;
});
EXPECT_CALL(*filesystem,
ReadFileStream("/sys/devices/system/cpu/cpufreq/policy1/stats/time_in_state", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1000 5\n2000 4");
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1000 7\n2000 10");
return true;
});
EXPECT_CALL(*filesystem,
ReadFileStream("/sys/devices/system/cpu/cpufreq/policy2/stats/time_in_state", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1500 1\n2500 23");
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1500 5\n2500 23");
return true;
});
CpuFrequencyReader reader(std::move(filesystem));
EXPECT_TRUE(reader.Init());
std::vector<CpuPolicyAverageFrequency> actual;
EXPECT_TRUE(reader.GetRecentCpuPolicyFrequencies(&actual));
EXPECT_EQ(actual, std::vector<CpuPolicyAverageFrequency>({
{.policyId = 1, .averageFrequencyHz = 1750},
{.policyId = 2, .averageFrequencyHz = 1500},
}));
}
TEST(CpuFrequencyReaderTest, getRecentCpuPolicyFrequencies_frequenciesChange) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
EXPECT_CALL(*filesystem, ListDirectory("/sys/devices/system/cpu/cpufreq", _))
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::vector<std::string>{"policy1"};
return true;
});
EXPECT_CALL(*filesystem,
ReadFileStream("/sys/devices/system/cpu/cpufreq/policy1/stats/time_in_state", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1000 5\n2000 4");
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1000 6\n2001 4");
return true;
});
CpuFrequencyReader reader(std::move(filesystem));
EXPECT_TRUE(reader.Init());
std::vector<CpuPolicyAverageFrequency> actual;
EXPECT_FALSE(reader.GetRecentCpuPolicyFrequencies(&actual));
}
TEST(CpuFrequencyReaderTest, getRecentCpuPolicyFrequencies_badFormat) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
EXPECT_CALL(*filesystem, ListDirectory("/sys/devices/system/cpu/cpufreq", _))
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::vector<std::string>{"policy1"};
return true;
});
EXPECT_CALL(*filesystem,
ReadFileStream("/sys/devices/system/cpu/cpufreq/policy1/stats/time_in_state", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1000 1");
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1000 2\nfoo");
return true;
});
CpuFrequencyReader reader(std::move(filesystem));
EXPECT_TRUE(reader.Init());
std::vector<CpuPolicyAverageFrequency> actual;
EXPECT_FALSE(reader.GetRecentCpuPolicyFrequencies(&actual));
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,139 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <gtest/gtest.h>
#include "adaptivecpu/CpuLoadReaderProcStat.h"
#include "mocks.h"
#define LOG_TAG "powerhal-adaptivecpu"
using testing::_;
using testing::ByMove;
using testing::Return;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
TEST(CpuLoadReaderProcStatTest, GetRecentCpuLoads) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
EXPECT_CALL(*filesystem, ReadFileStream("/proc/stat", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
std::stringstream ss;
ss << "bad line\n";
ss << "cpu1 100 0 0 50 0 0 0 0 0 0\n";
ss << "cpu2 200 0 0 50 0 0 0 0 0 0\n";
*result = std::make_unique<std::istringstream>(ss.str());
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
std::stringstream ss;
ss << "bad line\n";
ss << "cpu1 200 0 0 150 0 0 0 0 0 0\n";
ss << "cpu2 500 0 0 150 0 0 0 0 0 0\n";
*result = std::make_unique<std::istringstream>(ss.str());
return true;
});
CpuLoadReaderProcStat reader(std::move(filesystem));
reader.Init();
std::array<double, NUM_CPU_CORES> actualPercentages;
ASSERT_TRUE(reader.GetRecentCpuLoads(&actualPercentages));
std::array<double, NUM_CPU_CORES> expectedPercentages({0, 0.5, 0.25, 0, 0, 0, 0, 0});
ASSERT_EQ(actualPercentages, expectedPercentages);
}
TEST(CpuLoadReaderProcStatTest, GetRecentCpuLoads_failsWithMissingValues) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
EXPECT_CALL(*filesystem, ReadFileStream("/proc/stat", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
std::stringstream ss;
ss << "bad line\n";
ss << "cpu1 100 0 0 50 0 0 0\n";
ss << "cpu2 200 0 0 50 0 0 0\n";
*result = std::make_unique<std::istringstream>(ss.str());
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
std::stringstream ss;
ss << "bad line\n";
ss << "cpu1 200 0 0 150 0 0 0\n";
ss << "cpu2 500 0 0 150 0 0 0\n";
*result = std::make_unique<std::istringstream>(ss.str());
return true;
});
CpuLoadReaderProcStat reader(std::move(filesystem));
reader.Init();
std::array<double, NUM_CPU_CORES> actualPercentages;
ASSERT_FALSE(reader.GetRecentCpuLoads(&actualPercentages));
}
TEST(CpuLoadReaderProcStatTest, GetRecentCpuLoads_failsWithEmptyFile) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
EXPECT_CALL(*filesystem, ReadFileStream("/proc/stat", _))
.Times(2)
.WillRepeatedly([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("");
return true;
});
CpuLoadReaderProcStat reader(std::move(filesystem));
reader.Init();
std::array<double, NUM_CPU_CORES> actualPercentages;
ASSERT_FALSE(reader.GetRecentCpuLoads(&actualPercentages));
}
TEST(CpuLoadReaderProcStatTest, GetRecentCpuLoads_failsWithDifferentCpus) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
EXPECT_CALL(*filesystem, ReadFileStream("/proc/stat", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
std::stringstream ss;
ss << "bad line\n";
ss << "cpu1 100 0 0 50 0 0 0 0 0 0\n";
ss << "cpu2 200 0 0 50 0 0 0 0 0 0\n";
*result = std::make_unique<std::istringstream>(ss.str());
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
std::stringstream ss;
ss << "bad line\n";
ss << "cpu1 200 0 0 150 0 0 0 0 0 0\n";
ss << "cpu3 500 0 0 150 0 0 0 0 0 0\n";
*result = std::make_unique<std::istringstream>(ss.str());
return true;
});
CpuLoadReaderProcStat reader(std::move(filesystem));
reader.Init();
std::array<double, NUM_CPU_CORES> actualPercentages;
ASSERT_FALSE(reader.GetRecentCpuLoads(&actualPercentages));
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,126 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <gtest/gtest.h>
#include "adaptivecpu/CpuLoadReaderSysDevices.h"
#include "mocks.h"
#define LOG_TAG "powerhal-adaptivecpu"
using testing::_;
using testing::ByMove;
using testing::MatchesRegex;
using testing::Return;
using std::chrono_literals::operator""ms;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
TEST(CpuLoadReaderSysDevicesTest, GetRecentCpuLoads) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
std::unique_ptr<MockTimeSource> timeSource = std::make_unique<MockTimeSource>();
EXPECT_CALL(*filesystem, ListDirectory(MatchesRegex("/sys/devices/system/cpu/cpu0/cpuidle"), _))
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::vector<std::string>{"foo", "bar", "baz"};
return true;
});
EXPECT_CALL(*filesystem,
ListDirectory(MatchesRegex("/sys/devices/system/cpu/cpu0/cpuidle/(foo|bar)"), _))
.Times(2)
.WillRepeatedly([](auto _path __attribute__((unused)), auto result) {
*result = std::vector<std::string>{"abc", "time", "xyz"};
return true;
});
EXPECT_CALL(*filesystem,
ListDirectory(MatchesRegex("/sys/devices/system/cpu/cpu0/cpuidle/baz"), _))
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::vector<std::string>{"abc", "xyz"};
return true;
});
EXPECT_CALL(*filesystem, ReadFileStream("/sys/devices/system/cpu/cpu0/cpuidle/foo/time", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("100");
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("200");
return true;
});
EXPECT_CALL(*filesystem, ReadFileStream("/sys/devices/system/cpu/cpu0/cpuidle/bar/time", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("500");
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("700");
return true;
});
EXPECT_CALL(*filesystem, ReadFileStream("/sys/devices/system/cpu/cpu1/cpuidle/foo/time", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1000");
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("1010");
return true;
});
EXPECT_CALL(*filesystem, ReadFileStream("/sys/devices/system/cpu/cpu1/cpuidle/bar/time", _))
.Times(2)
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("50");
return true;
})
.WillOnce([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("70");
return true;
});
EXPECT_CALL(*filesystem,
ReadFileStream(
MatchesRegex("/sys/devices/system/cpu/cpu[2-7]/cpuidle/(foo|bar)/time"), _))
.WillRepeatedly([](auto _path __attribute__((unused)), auto result) {
*result = std::make_unique<std::istringstream>("0");
return true;
});
EXPECT_CALL(*timeSource, GetTime()).Times(2).WillOnce(Return(1ms)).WillOnce(Return(2ms));
CpuLoadReaderSysDevices reader(std::move(filesystem), std::move(timeSource));
ASSERT_TRUE(reader.Init());
std::array<double, NUM_CPU_CORES> actualPercentage;
reader.GetRecentCpuLoads(&actualPercentage);
std::array<double, NUM_CPU_CORES> expectedPercentage{0.3, 0.03, 0, 0, 0, 0, 0, 0};
ASSERT_EQ(actualPercentage, expectedPercentage);
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,211 @@
/*
* Copyright (C) 2022 The Android Open Source 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.
*/
#include <gtest/gtest.h>
#include "adaptivecpu/KernelCpuFeatureReader.h"
#include "mocks.h"
using testing::_;
using testing::ByMove;
using testing::MatchesRegex;
using testing::Return;
using std::chrono_literals::operator""ns;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
TEST(KernelCpuFeatureReaderTest, valid) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
std::unique_ptr<MockTimeSource> timeSource = std::make_unique<MockTimeSource>();
EXPECT_CALL(*timeSource, GetKernelTime())
.Times(2)
.WillOnce(Return(100ns))
.WillOnce(Return(200ns));
EXPECT_CALL(*filesystem, ReadFileStream("/proc/vendor_sched/acpu_stats", _))
.WillOnce([](auto path __attribute__((unused)), auto result) {
// Empty file, we will populate in ResetFileStream.
*result = std::make_unique<std::istringstream>("");
return true;
});
EXPECT_CALL(*filesystem, ResetFileStream(_))
.Times(2)
.WillOnce([](auto &result) {
std::array<acpu_stats, NUM_CPU_CORES> acpuStats{{
{.weighted_sum_freq = 100, .total_idle_time_ns = 100},
{.weighted_sum_freq = 100, .total_idle_time_ns = 100},
{.weighted_sum_freq = 100, .total_idle_time_ns = 100},
{.weighted_sum_freq = 100, .total_idle_time_ns = 100},
{.weighted_sum_freq = 200, .total_idle_time_ns = 200},
{.weighted_sum_freq = 200, .total_idle_time_ns = 200},
{.weighted_sum_freq = 300, .total_idle_time_ns = 200},
{.weighted_sum_freq = 300, .total_idle_time_ns = 200},
}};
char *bytes = reinterpret_cast<char *>(acpuStats.begin());
static_cast<std::istringstream &>(*result).str(
std::string(bytes, bytes + sizeof(acpuStats)));
return true;
})
.WillOnce([](auto &result) {
std::array<acpu_stats, NUM_CPU_CORES> acpuStats{{
{.weighted_sum_freq = 200, .total_idle_time_ns = 150},
{.weighted_sum_freq = 100, .total_idle_time_ns = 150},
{.weighted_sum_freq = 100, .total_idle_time_ns = 150},
{.weighted_sum_freq = 100, .total_idle_time_ns = 150},
{.weighted_sum_freq = 300, .total_idle_time_ns = 300},
{.weighted_sum_freq = 200, .total_idle_time_ns = 300},
{.weighted_sum_freq = 400, .total_idle_time_ns = 300},
{.weighted_sum_freq = 300, .total_idle_time_ns = 300},
}};
char *bytes = reinterpret_cast<char *>(acpuStats.begin());
static_cast<std::istringstream &>(*result).str(
std::string(bytes, bytes + sizeof(acpuStats)));
return true;
});
KernelCpuFeatureReader reader(std::move(filesystem), std::move(timeSource));
ASSERT_TRUE(reader.Init());
std::array<double, NUM_CPU_POLICIES> cpuPolicyAverageFrequencyHz;
std::array<double, NUM_CPU_CORES> cpuCoreIdleTimesPercentage;
ASSERT_TRUE(
reader.GetRecentCpuFeatures(&cpuPolicyAverageFrequencyHz, &cpuCoreIdleTimesPercentage));
std::array<double, NUM_CPU_POLICIES> expectedFrequencies{{1, 1, 1}};
std::array<double, NUM_CPU_CORES> expectedIdleTimes{{0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1}};
ASSERT_EQ(cpuPolicyAverageFrequencyHz, expectedFrequencies);
ASSERT_EQ(cpuCoreIdleTimesPercentage, expectedIdleTimes);
}
TEST(KernelCpuFeatureReaderTest, noFile) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
std::unique_ptr<MockTimeSource> timeSource = std::make_unique<MockTimeSource>();
EXPECT_CALL(*filesystem, ReadFileStream("/proc/vendor_sched/acpu_stats", _))
.WillOnce(Return(false));
KernelCpuFeatureReader reader(std::move(filesystem), std::move(timeSource));
ASSERT_FALSE(reader.Init());
}
TEST(KernelCpuFeatureReaderTest, frequencies_capsNegativeDiff) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
std::unique_ptr<MockTimeSource> timeSource = std::make_unique<MockTimeSource>();
EXPECT_CALL(*timeSource, GetKernelTime())
.Times(2)
.WillOnce(Return(100ns))
.WillOnce(Return(200ns));
EXPECT_CALL(*filesystem, ReadFileStream("/proc/vendor_sched/acpu_stats", _))
.WillOnce([](auto path __attribute__((unused)), auto result) {
// Empty file, we will populate in ResetFileStream.
*result = std::make_unique<std::istringstream>("");
return true;
});
EXPECT_CALL(*filesystem, ResetFileStream(_))
.Times(2)
.WillOnce([](auto &result) {
std::array<acpu_stats, NUM_CPU_CORES> acpuStats{{
{.weighted_sum_freq = 200, .total_idle_time_ns = 100},
}};
char *bytes = reinterpret_cast<char *>(acpuStats.begin());
static_cast<std::istringstream &>(*result).str(
std::string(bytes, bytes + sizeof(acpuStats)));
return true;
})
.WillOnce([](auto &result) {
std::array<acpu_stats, NUM_CPU_CORES> acpuStats{{
{.weighted_sum_freq = 100, .total_idle_time_ns = 150},
}};
char *bytes = reinterpret_cast<char *>(acpuStats.begin());
static_cast<std::istringstream &>(*result).str(
std::string(bytes, bytes + sizeof(acpuStats)));
return true;
});
KernelCpuFeatureReader reader(std::move(filesystem), std::move(timeSource));
ASSERT_TRUE(reader.Init());
std::array<double, NUM_CPU_POLICIES> cpuPolicyAverageFrequencyHz;
std::array<double, NUM_CPU_CORES> cpuCoreIdleTimesPercentage;
ASSERT_TRUE(
reader.GetRecentCpuFeatures(&cpuPolicyAverageFrequencyHz, &cpuCoreIdleTimesPercentage));
std::array<double, NUM_CPU_POLICIES> expectedFrequencies{{0}};
ASSERT_EQ(cpuPolicyAverageFrequencyHz, expectedFrequencies);
}
TEST(KernelCpuFeatureReaderTest, idleTimes_capsNegativeDiff) {
std::unique_ptr<MockFilesystem> filesystem = std::make_unique<MockFilesystem>();
std::unique_ptr<MockTimeSource> timeSource = std::make_unique<MockTimeSource>();
EXPECT_CALL(*timeSource, GetKernelTime())
.Times(2)
.WillOnce(Return(100ns))
.WillOnce(Return(200ns));
EXPECT_CALL(*filesystem, ReadFileStream("/proc/vendor_sched/acpu_stats", _))
.WillOnce([](auto path __attribute__((unused)), auto result) {
// Empty file, we will populate in ResetFileStream.
*result = std::make_unique<std::istringstream>("");
return true;
});
EXPECT_CALL(*filesystem, ResetFileStream(_))
.Times(2)
.WillOnce([](auto &result) {
std::array<acpu_stats, NUM_CPU_CORES> acpuStats{{
{.weighted_sum_freq = 100, .total_idle_time_ns = 150},
}};
char *bytes = reinterpret_cast<char *>(acpuStats.begin());
static_cast<std::istringstream &>(*result).str(
std::string(bytes, bytes + sizeof(acpuStats)));
return true;
})
.WillOnce([](auto &result) {
std::array<acpu_stats, NUM_CPU_CORES> acpuStats{{
{.weighted_sum_freq = 200, .total_idle_time_ns = 100},
}};
char *bytes = reinterpret_cast<char *>(acpuStats.begin());
static_cast<std::istringstream &>(*result).str(
std::string(bytes, bytes + sizeof(acpuStats)));
return true;
});
KernelCpuFeatureReader reader(std::move(filesystem), std::move(timeSource));
ASSERT_TRUE(reader.Init());
std::array<double, NUM_CPU_POLICIES> cpuPolicyAverageFrequencyHz;
std::array<double, NUM_CPU_CORES> cpuCoreIdleTimesPercentage;
ASSERT_TRUE(
reader.GetRecentCpuFeatures(&cpuPolicyAverageFrequencyHz, &cpuCoreIdleTimesPercentage));
std::array<double, NUM_CPU_CORES> expectedIdleTimes{{0}};
ASSERT_EQ(cpuCoreIdleTimesPercentage, expectedIdleTimes);
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,126 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <gtest/gtest.h>
#include <random>
#include <set>
#include "adaptivecpu/Model.h"
#include "mocks.h"
using std::chrono_literals::operator""ns;
using testing::_;
using testing::ByMove;
using testing::Return;
using testing::UnorderedElementsAre;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
TEST(ModelTest, ModelInput_SetCpuFreqiencies) {
const ModelInput expected{
.cpuPolicyAverageFrequencyHz = {100, 101, 102},
};
ModelInput actual;
ASSERT_TRUE(actual.SetCpuFreqiencies({
{.policyId = 0, .averageFrequencyHz = 100},
{.policyId = 4, .averageFrequencyHz = 101},
{.policyId = 6, .averageFrequencyHz = 102},
}));
ASSERT_EQ(actual, expected);
}
TEST(ModelTest, ModelInput_SetCpuFreqiencies_failsWithOutOfOrderFrquencies) {
ASSERT_FALSE(ModelInput().SetCpuFreqiencies({
{.policyId = 0, .averageFrequencyHz = 100},
{.policyId = 6, .averageFrequencyHz = 102},
{.policyId = 4, .averageFrequencyHz = 101},
}));
}
TEST(ModelTest, Run_randomInputs) {
std::default_random_engine generator;
std::uniform_real_distribution<double> frequencyDistribution(0, 1e6);
std::uniform_real_distribution<double> idleTimesDistribution(0, 1);
std::uniform_int_distribution<uint32_t> frameTimeDistribution(1, 100);
std::uniform_int_distribution<uint16_t> numRenderedFramesDistribution(1, 20);
std::uniform_int_distribution<uint32_t> throttleDecisionDistribution(0, 3);
const auto randomModelInput = [&]() {
return ModelInput{
.cpuPolicyAverageFrequencyHz = {frequencyDistribution(generator),
frequencyDistribution(generator),
frequencyDistribution(generator)},
.cpuCoreIdleTimesPercentage =
{idleTimesDistribution(generator), idleTimesDistribution(generator),
idleTimesDistribution(generator), idleTimesDistribution(generator),
idleTimesDistribution(generator), idleTimesDistribution(generator),
idleTimesDistribution(generator), idleTimesDistribution(generator)},
.workDurationFeatures =
{.averageDuration =
std::chrono::nanoseconds(frameTimeDistribution(generator)),
.maxDuration = std::chrono::nanoseconds(frameTimeDistribution(generator)),
.numMissedDeadlines = numRenderedFramesDistribution(generator),
.numDurations = numRenderedFramesDistribution(generator)},
.previousThrottleDecision =
static_cast<ThrottleDecision>(throttleDecisionDistribution(generator)),
};
};
for (int i = 0; i < 10; i++) {
std::deque<ModelInput> modelInputs{randomModelInput(), randomModelInput(),
randomModelInput()};
Model().Run(modelInputs, AdaptiveCpuConfig::DEFAULT);
}
}
TEST(ModelTest, Run_randomThrottling) {
ModelInput modelInput{
.cpuPolicyAverageFrequencyHz = {0, 0, 0},
.cpuCoreIdleTimesPercentage = {0, 0, 0, 0, 0, 0, 0, 0},
.workDurationFeatures = {.averageDuration = 0ns,
.maxDuration = 0ns,
.numMissedDeadlines = 0,
.numDurations = 0},
.previousThrottleDecision = ThrottleDecision::NO_THROTTLE,
};
std::deque<ModelInput> modelInputs{modelInput, modelInput, modelInput};
AdaptiveCpuConfig config = AdaptiveCpuConfig::DEFAULT;
config.randomThrottleOptions = {ThrottleDecision::THROTTLE_70, ThrottleDecision::THROTTLE_80};
config.randomThrottleDecisionProbability = 1;
std::set<ThrottleDecision> actualThrottleDecisions;
Model model;
for (int i = 0; i < 100; i++) {
ThrottleDecision throttleDecision = model.Run(modelInputs, config);
actualThrottleDecisions.insert(throttleDecision);
}
ASSERT_THAT(actualThrottleDecisions,
UnorderedElementsAre(ThrottleDecision::THROTTLE_70, ThrottleDecision::THROTTLE_80));
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,126 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <gtest/gtest.h>
#include "adaptivecpu/WorkDurationProcessor.h"
using ::aidl::android::hardware::power::WorkDuration;
using std::chrono_literals::operator""ns;
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
static const std::chrono::nanoseconds kNormalTargetDuration = 16666666ns;
TEST(WorkDurationProcessorTest, GetFeatures) {
WorkDurationProcessor processor;
ASSERT_TRUE(processor.ReportWorkDurations(
std::vector<WorkDuration>{
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count()},
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count() * 3}},
kNormalTargetDuration));
const WorkDurationFeatures expected = {.averageDuration = kNormalTargetDuration * 2,
.maxDuration = kNormalTargetDuration * 3,
.numMissedDeadlines = 1,
.numDurations = 2};
const WorkDurationFeatures actual = processor.GetFeatures();
ASSERT_EQ(actual, expected);
}
TEST(WorkDurationProcessorTest, GetFeatures_multipleBatches) {
WorkDurationProcessor processor;
ASSERT_TRUE(processor.ReportWorkDurations(
std::vector<WorkDuration>{
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count()},
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count() * 3}},
kNormalTargetDuration));
ASSERT_TRUE(processor.ReportWorkDurations(
std::vector<WorkDuration>{
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count() * 6},
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count() * 2}},
kNormalTargetDuration));
const WorkDurationFeatures expected = {.averageDuration = kNormalTargetDuration * 3,
.maxDuration = kNormalTargetDuration * 6,
.numMissedDeadlines = 3,
.numDurations = 4};
const WorkDurationFeatures actual = processor.GetFeatures();
ASSERT_EQ(actual, expected);
}
TEST(WorkDurationProcessorTest, GetFeatures_scalesDifferentTargetDurations) {
WorkDurationProcessor processor;
ASSERT_TRUE(processor.ReportWorkDurations(
std::vector<WorkDuration>{
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count() * 2},
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count() * 6}},
kNormalTargetDuration * 2));
const WorkDurationFeatures expected = {.averageDuration = kNormalTargetDuration * 2,
.maxDuration = kNormalTargetDuration * 3,
.numMissedDeadlines = 1,
.numDurations = 2};
const WorkDurationFeatures actual = processor.GetFeatures();
ASSERT_EQ(actual, expected);
}
TEST(WorkDurationProcessorTest, GetFeatures_noFrames) {
WorkDurationProcessor processor;
const WorkDurationFeatures expected = {
.averageDuration = 0ns, .maxDuration = 0ns, .numMissedDeadlines = 0, .numDurations = 0};
const WorkDurationFeatures actual = processor.GetFeatures();
ASSERT_EQ(actual, expected);
}
TEST(WorkDurationProcessorTest, HasWorkDurations) {
WorkDurationProcessor processor;
ASSERT_FALSE(processor.HasWorkDurations());
ASSERT_TRUE(processor.ReportWorkDurations(
std::vector<WorkDuration>{
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count()}},
kNormalTargetDuration * 2));
ASSERT_TRUE(processor.HasWorkDurations());
processor.GetFeatures();
ASSERT_FALSE(processor.HasWorkDurations());
}
TEST(WorkDurationProcessorTest, GetFeatures_tooManyUnprocessedThenClears) {
WorkDurationProcessor processor;
for (int i = 0; i < 1000; i++) {
ASSERT_TRUE(processor.ReportWorkDurations(
std::vector<WorkDuration>{
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count()}},
kNormalTargetDuration));
}
ASSERT_FALSE(processor.ReportWorkDurations(
std::vector<WorkDuration>{
{.timeStampNanos = 0, .durationNanos = kNormalTargetDuration.count()}},
kNormalTargetDuration));
ASSERT_EQ(processor.GetFeatures().numDurations, 0);
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,53 @@
/*
* Copyright (C) 2021 The Android Open Source 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.
*/
#include <gmock/gmock.h>
#include "adaptivecpu/IFilesystem.h"
#include "adaptivecpu/ITimeSource.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
class MockFilesystem : public IFilesystem {
public:
~MockFilesystem() override {}
MOCK_METHOD(bool, ListDirectory, (const std::string &path, std::vector<std::string> *result),
(const, override));
MOCK_METHOD(bool, ReadFileStream,
(const std::string &path, std::unique_ptr<std::istream> *result),
(const, override));
MOCK_METHOD(bool, ResetFileStream, (const std::unique_ptr<std::istream> &fileStream),
(const, override));
};
class MockTimeSource : public ITimeSource {
public:
~MockTimeSource() override {}
MOCK_METHOD(std::chrono::nanoseconds, GetTime, (), (const, override));
MOCK_METHOD(std::chrono::nanoseconds, GetKernelTime, (), (const, override));
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -13,8 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#define LOG_TAG "powerhal-libperfmgr" #define LOG_TAG "powerhal-libperfmgr"
#include "Power.h" #include "Power.h"
#include <android-base/file.h> #include <android-base/file.h>
#include <android-base/logging.h> #include <android-base/logging.h>
#include <android-base/properties.h> #include <android-base/properties.h>
@ -22,29 +25,35 @@
#include <android-base/strings.h> #include <android-base/strings.h>
#include <perfmgr/HintManager.h> #include <perfmgr/HintManager.h>
#include <utils/Log.h> #include <utils/Log.h>
#include <mutex> #include <mutex>
#include "PowerHintSession.h" #include "PowerHintSession.h"
#include "PowerSessionManager.h" #include "PowerSessionManager.h"
#include "disp-power/DisplayLowPower.h"
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
using ::aidl::google::hardware::power::impl::pixel::PowerHintSession; using ::aidl::google::hardware::power::impl::pixel::PowerHintSession;
using ::android::perfmgr::HintManager; using ::android::perfmgr::HintManager;
#ifdef MODE_EXT
extern bool isDeviceSpecificModeSupported(Mode type, bool* _aidl_return);
extern bool setDeviceSpecificMode(Mode type, bool enabled);
#endif
constexpr char kPowerHalStateProp[] = "vendor.powerhal.state"; constexpr char kPowerHalStateProp[] = "vendor.powerhal.state";
constexpr char kPowerHalAudioProp[] = "vendor.powerhal.audio"; constexpr char kPowerHalAudioProp[] = "vendor.powerhal.audio";
constexpr char kPowerHalRenderingProp[] = "vendor.powerhal.rendering"; constexpr char kPowerHalRenderingProp[] = "vendor.powerhal.rendering";
Power::Power()
: mInteractionHandler(nullptr), Power::Power(std::shared_ptr<DisplayLowPower> dlpw, std::shared_ptr<AdaptiveCpu> adaptiveCpu)
: mDisplayLowPower(dlpw),
mAdaptiveCpu(adaptiveCpu),
mInteractionHandler(nullptr),
mSustainedPerfModeOn(false) { mSustainedPerfModeOn(false) {
mInteractionHandler = std::make_unique<InteractionHandler>(); mInteractionHandler = std::make_unique<InteractionHandler>();
mInteractionHandler->Init(); mInteractionHandler->Init();
std::string state = ::android::base::GetProperty(kPowerHalStateProp, ""); std::string state = ::android::base::GetProperty(kPowerHalStateProp, "");
if (state == "SUSTAINED_PERFORMANCE") { if (state == "SUSTAINED_PERFORMANCE") {
LOG(INFO) << "Initialize with SUSTAINED_PERFORMANCE on"; LOG(INFO) << "Initialize with SUSTAINED_PERFORMANCE on";
@ -53,34 +62,60 @@ Power::Power()
} else { } else {
LOG(INFO) << "Initialize PowerHAL"; LOG(INFO) << "Initialize PowerHAL";
} }
state = ::android::base::GetProperty(kPowerHalAudioProp, ""); state = ::android::base::GetProperty(kPowerHalAudioProp, "");
if (state == "AUDIO_STREAMING_LOW_LATENCY") { if (state == "AUDIO_STREAMING_LOW_LATENCY") {
LOG(INFO) << "Initialize with AUDIO_LOW_LATENCY on"; LOG(INFO) << "Initialize with AUDIO_LOW_LATENCY on";
HintManager::GetInstance()->DoHint(state); HintManager::GetInstance()->DoHint(state);
} }
state = ::android::base::GetProperty(kPowerHalRenderingProp, ""); state = ::android::base::GetProperty(kPowerHalRenderingProp, "");
if (state == "EXPENSIVE_RENDERING") { if (state == "EXPENSIVE_RENDERING") {
LOG(INFO) << "Initialize with EXPENSIVE_RENDERING on"; LOG(INFO) << "Initialize with EXPENSIVE_RENDERING on";
HintManager::GetInstance()->DoHint("EXPENSIVE_RENDERING"); HintManager::GetInstance()->DoHint("EXPENSIVE_RENDERING");
} }
} }
static int sysfs_write(const char *path, const char *s)
{
char buf[80];
int len;
int ret = 0;
int fd = open(path, O_WRONLY);
if (fd < 0) {
strerror_r(errno, buf, sizeof(buf));
ALOGE("Error opening %s: %s\n", path, buf);
return -1 ;
}
len = write(fd, s, strlen(s));
if (len < 0) {
strerror_r(errno, buf, sizeof(buf));
ALOGE("Error writing to %s: %s\n", path, buf);
ret = -1;
}
close(fd);
return ret;
}
ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) { ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
LOG(DEBUG) << "Power setMode: " << toString(type) << " to: " << enabled; LOG(DEBUG) << "Power setMode: " << toString(type) << " to: " << enabled;
if (HintManager::GetInstance()->GetAdpfProfile() && if (HintManager::GetInstance()->GetAdpfProfile() &&
HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs > 0) { HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs > 0) {
PowerSessionManager::getInstance()->updateHintMode(toString(type), enabled); PowerSessionManager::getInstance()->updateHintMode(toString(type), enabled);
} }
#ifdef MODE_EXT
if (setDeviceSpecificMode(type, enabled)) {
return ndk::ScopedAStatus::ok();
}
#endif
switch (type) { switch (type) {
#ifdef TAP_TO_WAKE_NODE
case Mode::DOUBLE_TAP_TO_WAKE: case Mode::DOUBLE_TAP_TO_WAKE:
::android::base::WriteStringToFile(enabled ? "1" : "0", TAP_TO_WAKE_NODE, true); {
sysfs_write("/sys/class/touch/tp_dev/gesture_on", enabled ? "1" : "0");
}
break;
case Mode::LOW_POWER:
break; break;
#endif
case Mode::SUSTAINED_PERFORMANCE: case Mode::SUSTAINED_PERFORMANCE:
if (enabled) { if (enabled) {
HintManager::GetInstance()->DoHint("SUSTAINED_PERFORMANCE"); HintManager::GetInstance()->DoHint("SUSTAINED_PERFORMANCE");
@ -92,10 +127,6 @@ ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
break; break;
} }
[[fallthrough]]; [[fallthrough]];
#ifndef TAP_TO_WAKE_NODE
case Mode::DOUBLE_TAP_TO_WAKE:
[[fallthrough]];
#endif
case Mode::FIXED_PERFORMANCE: case Mode::FIXED_PERFORMANCE:
[[fallthrough]]; [[fallthrough]];
case Mode::EXPENSIVE_RENDERING: case Mode::EXPENSIVE_RENDERING:
@ -108,6 +139,8 @@ ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
[[fallthrough]]; [[fallthrough]];
case Mode::AUDIO_STREAMING_LOW_LATENCY: case Mode::AUDIO_STREAMING_LOW_LATENCY:
[[fallthrough]]; [[fallthrough]];
case Mode::GAME_LOADING:
[[fallthrough]];
default: default:
if (enabled) { if (enabled) {
HintManager::GetInstance()->DoHint(toString(type)); HintManager::GetInstance()->DoHint(toString(type));
@ -116,24 +149,21 @@ ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
} }
break; break;
} }
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus Power::isModeSupported(Mode type, bool *_aidl_return) { ndk::ScopedAStatus Power::isModeSupported(Mode type, bool *_aidl_return) {
#ifdef MODE_EXT
if (isDeviceSpecificModeSupported(type, _aidl_return)) {
return ndk::ScopedAStatus::ok();
}
#endif
bool supported = HintManager::GetInstance()->IsHintSupported(toString(type)); bool supported = HintManager::GetInstance()->IsHintSupported(toString(type));
#ifdef TAP_TO_WAKE_NODE // LOW_POWER and DOUBLE_TAP_TO_WAKE handled insides PowerHAL specifically
if (type == Mode::DOUBLE_TAP_TO_WAKE) { if (type == Mode::LOW_POWER || type == Mode::DOUBLE_TAP_TO_WAKE) {
supported = true; supported = true;
} }
#endif
LOG(INFO) << "Power mode " << toString(type) << " isModeSupported: " << supported; LOG(INFO) << "Power mode " << toString(type) << " isModeSupported: " << supported;
*_aidl_return = supported; *_aidl_return = supported;
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) { ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
LOG(DEBUG) << "Power setBoost: " << toString(type) << " duration: " << durationMs; LOG(DEBUG) << "Power setBoost: " << toString(type) << " duration: " << durationMs;
if (HintManager::GetInstance()->GetAdpfProfile() && if (HintManager::GetInstance()->GetAdpfProfile() &&
@ -167,17 +197,21 @@ ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
} }
break; break;
} }
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool *_aidl_return) { ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool *_aidl_return) {
bool supported = HintManager::GetInstance()->IsHintSupported(toString(type)); bool supported = HintManager::GetInstance()->IsHintSupported(toString(type));
LOG(INFO) << "Power boost " << toString(type) << " isBoostSupported: " << supported; LOG(INFO) << "Power boost " << toString(type) << " isBoostSupported: " << supported;
*_aidl_return = supported; *_aidl_return = supported;
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
constexpr const char *boolToString(bool b) { constexpr const char *boolToString(bool b) {
return b ? "true" : "false"; return b ? "true" : "false";
} }
binder_status_t Power::dump(int fd, const char **, uint32_t) { binder_status_t Power::dump(int fd, const char **, uint32_t) {
std::string buf(::android::base::StringPrintf( std::string buf(::android::base::StringPrintf(
"HintManager Running: %s\n" "HintManager Running: %s\n"
@ -187,12 +221,14 @@ binder_status_t Power::dump(int fd, const char **, uint32_t) {
// Dump nodes through libperfmgr // Dump nodes through libperfmgr
HintManager::GetInstance()->DumpToFd(fd); HintManager::GetInstance()->DumpToFd(fd);
PowerSessionManager::getInstance()->dumpToFd(fd); PowerSessionManager::getInstance()->dumpToFd(fd);
mAdaptiveCpu->DumpToFd(fd);
if (!::android::base::WriteStringToFd(buf, fd)) { if (!::android::base::WriteStringToFd(buf, fd)) {
PLOG(ERROR) << "Failed to dump state to fd"; PLOG(ERROR) << "Failed to dump state to fd";
} }
fsync(fd); fsync(fd);
return STATUS_OK; return STATUS_OK;
} }
ndk::ScopedAStatus Power::createHintSession(int32_t tgid, int32_t uid, ndk::ScopedAStatus Power::createHintSession(int32_t tgid, int32_t uid,
const std::vector<int32_t> &threadIds, const std::vector<int32_t> &threadIds,
int64_t durationNanos, int64_t durationNanos,
@ -208,10 +244,11 @@ ndk::ScopedAStatus Power::createHintSession(int32_t tgid, int32_t uid,
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
} }
std::shared_ptr<IPowerHintSession> session = ndk::SharedRefBase::make<PowerHintSession>( std::shared_ptr<IPowerHintSession> session = ndk::SharedRefBase::make<PowerHintSession>(
tgid, uid, threadIds, durationNanos); mAdaptiveCpu, tgid, uid, threadIds, durationNanos);
*_aidl_return = session; *_aidl_return = session;
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t *outNanoseconds) { ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t *outNanoseconds) {
*outNanoseconds = HintManager::GetInstance()->GetAdpfProfile() *outNanoseconds = HintManager::GetInstance()->GetAdpfProfile()
? HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs ? HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs
@ -219,8 +256,10 @@ ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t *outNanoseconds) {
if (*outNanoseconds <= 0) { if (*outNanoseconds <= 0) {
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
} }
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -13,24 +13,33 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <aidl/android/hardware/power/BnPower.h> #include <aidl/android/hardware/power/BnPower.h>
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <thread> #include <thread>
#include "InteractionHandler.h"
#include "adaptivecpu/AdaptiveCpu.h"
#include "disp-power/DisplayLowPower.h"
#include "disp-power/InteractionHandler.h"
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
using ::aidl::android::hardware::power::Boost; using ::aidl::android::hardware::power::Boost;
using ::aidl::android::hardware::power::IPowerHintSession; using ::aidl::android::hardware::power::IPowerHintSession;
using ::aidl::android::hardware::power::Mode; using ::aidl::android::hardware::power::Mode;
class Power : public ::aidl::android::hardware::power::BnPower { class Power : public ::aidl::android::hardware::power::BnPower {
public: public:
Power(); Power(std::shared_ptr<DisplayLowPower> dlpw, std::shared_ptr<AdaptiveCpu> adaptiveCpu);
ndk::ScopedAStatus setMode(Mode type, bool enabled) override; ndk::ScopedAStatus setMode(Mode type, bool enabled) override;
ndk::ScopedAStatus isModeSupported(Mode type, bool *_aidl_return) override; ndk::ScopedAStatus isModeSupported(Mode type, bool *_aidl_return) override;
ndk::ScopedAStatus setBoost(Boost type, int32_t durationMs) override; ndk::ScopedAStatus setBoost(Boost type, int32_t durationMs) override;
@ -41,10 +50,14 @@ class Power : public ::aidl::android::hardware::power::BnPower {
std::shared_ptr<IPowerHintSession> *_aidl_return) override; std::shared_ptr<IPowerHintSession> *_aidl_return) override;
ndk::ScopedAStatus getHintSessionPreferredRate(int64_t *outNanoseconds) override; ndk::ScopedAStatus getHintSessionPreferredRate(int64_t *outNanoseconds) override;
binder_status_t dump(int fd, const char **args, uint32_t numArgs) override; binder_status_t dump(int fd, const char **args, uint32_t numArgs) override;
private: private:
std::shared_ptr<DisplayLowPower> mDisplayLowPower;
std::shared_ptr<AdaptiveCpu> mAdaptiveCpu;
std::unique_ptr<InteractionHandler> mInteractionHandler; std::unique_ptr<InteractionHandler> mInteractionHandler;
std::atomic<bool> mSustainedPerfModeOn; std::atomic<bool> mSustainedPerfModeOn;
}; };
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -13,8 +13,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#define LOG_TAG "android.hardware.power-service.xiaomi.ext-libperfmgr"
#define LOG_TAG "android.hardware.power-service.pixel.ext-libperfmgr"
#include "PowerExt.h" #include "PowerExt.h"
#include <android-base/file.h> #include <android-base/file.h>
#include <android-base/logging.h> #include <android-base/logging.h>
#include <android-base/properties.h> #include <android-base/properties.h>
@ -22,17 +25,23 @@
#include <android-base/strings.h> #include <android-base/strings.h>
#include <perfmgr/HintManager.h> #include <perfmgr/HintManager.h>
#include <utils/Log.h> #include <utils/Log.h>
#include <mutex> #include <mutex>
#include "PowerSessionManager.h" #include "PowerSessionManager.h"
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
using ::android::perfmgr::HintManager; using ::android::perfmgr::HintManager;
ndk::ScopedAStatus PowerExt::setMode(const std::string &mode, bool enabled) { ndk::ScopedAStatus PowerExt::setMode(const std::string &mode, bool enabled) {
LOG(DEBUG) << "PowerExt setMode: " << mode << " to: " << enabled; LOG(DEBUG) << "PowerExt setMode: " << mode << " to: " << enabled;
if (enabled) { if (enabled) {
HintManager::GetInstance()->DoHint(mode); HintManager::GetInstance()->DoHint(mode);
} else { } else {
@ -42,20 +51,29 @@ ndk::ScopedAStatus PowerExt::setMode(const std::string &mode, bool enabled) {
HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs > 0) { HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs > 0) {
PowerSessionManager::getInstance()->updateHintMode(mode, enabled); PowerSessionManager::getInstance()->updateHintMode(mode, enabled);
} }
if (mode == AdaptiveCpu::HINT_NAME) {
LOG(DEBUG) << "AdaptiveCpu intercepted hint";
mAdaptiveCpu->HintReceived(enabled);
}
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus PowerExt::isModeSupported(const std::string &mode, bool *_aidl_return) { ndk::ScopedAStatus PowerExt::isModeSupported(const std::string &mode, bool *_aidl_return) {
bool supported = HintManager::GetInstance()->IsHintSupported(mode); bool supported = HintManager::GetInstance()->IsHintSupported(mode);
LOG(INFO) << "PowerExt mode " << mode << " isModeSupported: " << supported; LOG(INFO) << "PowerExt mode " << mode << " isModeSupported: " << supported;
*_aidl_return = supported; *_aidl_return = supported;
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus PowerExt::setBoost(const std::string &boost, int32_t durationMs) { ndk::ScopedAStatus PowerExt::setBoost(const std::string &boost, int32_t durationMs) {
LOG(DEBUG) << "PowerExt setBoost: " << boost << " duration: " << durationMs; LOG(DEBUG) << "PowerExt setBoost: " << boost << " duration: " << durationMs;
if (HintManager::GetInstance()->GetAdpfProfile() && if (HintManager::GetInstance()->GetAdpfProfile() &&
HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs > 0) { HintManager::GetInstance()->GetAdpfProfile()->mReportingRateLimitNs > 0) {
PowerSessionManager::getInstance()->updateHintBoost(boost, durationMs); PowerSessionManager::getInstance()->updateHintBoost(boost, durationMs);
} }
if (durationMs > 0) { if (durationMs > 0) {
HintManager::GetInstance()->DoHint(boost, std::chrono::milliseconds(durationMs)); HintManager::GetInstance()->DoHint(boost, std::chrono::milliseconds(durationMs));
} else if (durationMs == 0) { } else if (durationMs == 0) {
@ -63,14 +81,17 @@ ndk::ScopedAStatus PowerExt::setBoost(const std::string &boost, int32_t duration
} else { } else {
HintManager::GetInstance()->EndHint(boost); HintManager::GetInstance()->EndHint(boost);
} }
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus PowerExt::isBoostSupported(const std::string &boost, bool *_aidl_return) { ndk::ScopedAStatus PowerExt::isBoostSupported(const std::string &boost, bool *_aidl_return) {
bool supported = HintManager::GetInstance()->IsHintSupported(boost); bool supported = HintManager::GetInstance()->IsHintSupported(boost);
LOG(INFO) << "PowerExt boost " << boost << " isBoostSupported: " << supported; LOG(INFO) << "PowerExt boost " << boost << " isBoostSupported: " << supported;
*_aidl_return = supported; *_aidl_return = supported;
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -13,27 +13,40 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <aidl/google/hardware/power/extension/pixel/BnPowerExt.h>
#include <perfmgr/HintManager.h>
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <thread> #include <thread>
#include <aidl/google/hardware/power/extension/pixel/BnPowerExt.h>
#include <perfmgr/HintManager.h> #include "adaptivecpu/AdaptiveCpu.h"
#include "disp-power/DisplayLowPower.h"
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
class PowerExt : public ::aidl::google::hardware::power::extension::pixel::BnPowerExt { class PowerExt : public ::aidl::google::hardware::power::extension::pixel::BnPowerExt {
public: public:
PowerExt() {} PowerExt(std::shared_ptr<DisplayLowPower> dlpw, std::shared_ptr<AdaptiveCpu> acpu)
: mDisplayLowPower(dlpw), mAdaptiveCpu(acpu) {}
ndk::ScopedAStatus setMode(const std::string &mode, bool enabled) override; ndk::ScopedAStatus setMode(const std::string &mode, bool enabled) override;
ndk::ScopedAStatus isModeSupported(const std::string &mode, bool *_aidl_return) override; ndk::ScopedAStatus isModeSupported(const std::string &mode, bool *_aidl_return) override;
ndk::ScopedAStatus setBoost(const std::string &boost, int32_t durationMs) override; ndk::ScopedAStatus setBoost(const std::string &boost, int32_t durationMs) override;
ndk::ScopedAStatus isBoostSupported(const std::string &boost, bool *_aidl_return) override; ndk::ScopedAStatus isBoostSupported(const std::string &boost, bool *_aidl_return) override;
private: private:
std::shared_ptr<DisplayLowPower> mDisplayLowPower;
std::shared_ptr<AdaptiveCpu> mAdaptiveCpu;
}; };
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -13,9 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#define LOG_TAG "powerhal-libperfmgr" #define LOG_TAG "powerhal-libperfmgr"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL) #define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "PowerHintSession.h" #include "PowerHintSession.h"
#include <android-base/logging.h> #include <android-base/logging.h>
#include <android-base/parsedouble.h> #include <android-base/parsedouble.h>
#include <android-base/properties.h> #include <android-base/properties.h>
@ -25,30 +28,35 @@
#include <sys/syscall.h> #include <sys/syscall.h>
#include <time.h> #include <time.h>
#include <utils/Trace.h> #include <utils/Trace.h>
#include <atomic> #include <atomic>
#include "PowerSessionManager.h" #include "PowerSessionManager.h"
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
using ::android::base::StringPrintf; using ::android::base::StringPrintf;
using ::android::perfmgr::AdpfConfig; using ::android::perfmgr::AdpfConfig;
using ::android::perfmgr::HintManager; using ::android::perfmgr::HintManager;
using std::chrono::duration_cast; using std::chrono::duration_cast;
using std::chrono::nanoseconds; using std::chrono::nanoseconds;
namespace { namespace {
static inline int64_t ns_to_100us(int64_t ns) { static inline int64_t ns_to_100us(int64_t ns) {
return ns / 100000; return ns / 100000;
} }
} // namespace
int64_t PowerHintSession::convertWorkDurationToBoostByPid( static int64_t convertWorkDurationToBoostByPid(std::shared_ptr<AdpfConfig> adpfConfig,
const std::vector<WorkDuration> &actualDurations) { nanoseconds targetDuration,
std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile(); const std::vector<WorkDuration> &actualDurations,
const nanoseconds &targetDuration = mDescriptor->duration; int64_t *integral_error, int64_t *previous_error,
int64_t &integral_error = mDescriptor->integral_error; const std::string &idstr) {
int64_t &previous_error = mDescriptor->previous_error;
uint64_t samplingWindowP = adpfConfig->mSamplingWindowP; uint64_t samplingWindowP = adpfConfig->mSamplingWindowP;
uint64_t samplingWindowI = adpfConfig->mSamplingWindowI; uint64_t samplingWindowI = adpfConfig->mSamplingWindowI;
uint64_t samplingWindowD = adpfConfig->mSamplingWindowD; uint64_t samplingWindowD = adpfConfig->mSamplingWindowD;
@ -72,77 +80,109 @@ int64_t PowerHintSession::convertWorkDurationToBoostByPid(
// PID control algorithm // PID control algorithm
int64_t error = ns_to_100us(actualDurationNanos - targetDurationNanos); int64_t error = ns_to_100us(actualDurationNanos - targetDurationNanos);
if (i >= d_start) { if (i >= d_start) {
derivative_sum += error - previous_error; derivative_sum += error - (*previous_error);
} }
if (i >= p_start) { if (i >= p_start) {
err_sum += error; err_sum += error;
} }
if (i >= i_start) { if (i >= i_start) {
integral_error += error * dt; *integral_error = *integral_error + error * dt;
integral_error = std::min(adpfConfig->getPidIHighDivI(), integral_error); *integral_error = std::min(adpfConfig->getPidIHighDivI(), *integral_error);
integral_error = std::max(adpfConfig->getPidILowDivI(), integral_error); *integral_error = std::max(adpfConfig->getPidILowDivI(), *integral_error);
} }
previous_error = error; *previous_error = error;
} }
int64_t pOut = static_cast<int64_t>((err_sum > 0 ? adpfConfig->mPidPo : adpfConfig->mPidPu) * int64_t pOut = static_cast<int64_t>((err_sum > 0 ? adpfConfig->mPidPo : adpfConfig->mPidPu) *
err_sum / (length - p_start)); err_sum / (length - p_start));
int64_t iOut = static_cast<int64_t>(adpfConfig->mPidI * integral_error); int64_t iOut = static_cast<int64_t>(adpfConfig->mPidI * (*integral_error));
int64_t dOut = int64_t dOut =
static_cast<int64_t>((derivative_sum > 0 ? adpfConfig->mPidDo : adpfConfig->mPidDu) * static_cast<int64_t>((derivative_sum > 0 ? adpfConfig->mPidDo : adpfConfig->mPidDu) *
derivative_sum / dt / (length - d_start)); derivative_sum / dt / (length - d_start));
int64_t output = pOut + iOut + dOut; int64_t output = pOut + iOut + dOut;
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("pid.err", err_sum / (length - p_start)); std::string sz = StringPrintf("adpf.%s-pid.err", idstr.c_str());
traceSessionVal("pid.integral", integral_error); ATRACE_INT(sz.c_str(), err_sum / (length - p_start));
traceSessionVal("pid.derivative", derivative_sum / dt / (length - d_start)); sz = StringPrintf("adpf.%s-pid.integral", idstr.c_str());
traceSessionVal("pid.pOut", pOut); ATRACE_INT(sz.c_str(), *integral_error);
traceSessionVal("pid.iOut", iOut); sz = StringPrintf("adpf.%s-pid.derivative", idstr.c_str());
traceSessionVal("pid.dOut", dOut); ATRACE_INT(sz.c_str(), derivative_sum / dt / (length - d_start));
traceSessionVal("pid.output", output); sz = StringPrintf("adpf.%s-pid.pOut", idstr.c_str());
ATRACE_INT(sz.c_str(), pOut);
sz = StringPrintf("adpf.%s-pid.iOut", idstr.c_str());
ATRACE_INT(sz.c_str(), iOut);
sz = StringPrintf("adpf.%s-pid.dOut", idstr.c_str());
ATRACE_INT(sz.c_str(), dOut);
sz = StringPrintf("adpf.%s-pid.output", idstr.c_str());
ATRACE_INT(sz.c_str(), output);
} }
return output; return output;
} }
PowerHintSession::PowerHintSession(int32_t tgid, int32_t uid, const std::vector<int32_t> &threadIds,
int64_t durationNanos) { } // namespace
PowerHintSession::PowerHintSession(std::shared_ptr<AdaptiveCpu> adaptiveCpu, int32_t tgid,
int32_t uid, const std::vector<int32_t> &threadIds,
int64_t durationNanos)
: mAdaptiveCpu(adaptiveCpu) {
mDescriptor = new AppHintDesc(tgid, uid, threadIds); mDescriptor = new AppHintDesc(tgid, uid, threadIds);
mDescriptor->duration = std::chrono::nanoseconds(durationNanos); mDescriptor->duration = std::chrono::nanoseconds(durationNanos);
mIdString = StringPrintf("%" PRId32 "-%" PRId32 "-%" PRIxPTR, mDescriptor->tgid,
mDescriptor->uid, reinterpret_cast<uintptr_t>(this) & 0xffff);
mStaleTimerHandler = sp<StaleTimerHandler>(new StaleTimerHandler(this)); mStaleTimerHandler = sp<StaleTimerHandler>(new StaleTimerHandler(this));
mEarlyBoostHandler = sp<EarlyBoostHandler>(new EarlyBoostHandler(this));
mPowerManagerHandler = PowerSessionManager::getInstance(); mPowerManagerHandler = PowerSessionManager::getInstance();
mLastUpdatedTime.store(std::chrono::steady_clock::now()); mLastUpdatedTime.store(std::chrono::steady_clock::now());
mLastStartedTimeNs =
std::chrono::duration_cast<std::chrono::nanoseconds>(
(std::chrono::steady_clock::now() - mDescriptor->duration).time_since_epoch())
.count();
mLastDurationNs = durationNanos;
mWorkPeriodNs = durationNanos;
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("target", mDescriptor->duration.count()); const std::string idstr = getIdString();
traceSessionVal("active", mDescriptor->is_active.load()); std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
sz = StringPrintf("adpf.%s-active", idstr.c_str());
ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
} }
PowerSessionManager::getInstance()->addPowerSession(this); PowerSessionManager::getInstance()->addPowerSession(this);
// init boost // init boost
setSessionUclampMin(HintManager::GetInstance()->GetAdpfProfile()->mUclampMinInit); setSessionUclampMin(HintManager::GetInstance()->GetAdpfProfile()->mUclampMinInit);
ALOGV("PowerHintSession created: %s", mDescriptor->toString().c_str()); ALOGV("PowerHintSession created: %s", mDescriptor->toString().c_str());
} }
PowerHintSession::~PowerHintSession() { PowerHintSession::~PowerHintSession() {
close(); close();
ALOGV("PowerHintSession deleted: %s", mDescriptor->toString().c_str()); ALOGV("PowerHintSession deleted: %s", mDescriptor->toString().c_str());
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("target", 0); const std::string idstr = getIdString();
traceSessionVal("actl_last", 0); std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
traceSessionVal("active", 0); ATRACE_INT(sz.c_str(), 0);
sz = StringPrintf("adpf.%s-actl_last", idstr.c_str());
ATRACE_INT(sz.c_str(), 0);
sz = sz = StringPrintf("adpf.%s-active", idstr.c_str());
ATRACE_INT(sz.c_str(), 0);
} }
delete mDescriptor; delete mDescriptor;
} }
void PowerHintSession::traceSessionVal(char const *identifier, int64_t val) const {
ATRACE_INT(StringPrintf("adpf.%s-%s", mIdString.c_str(), identifier).c_str(), val); std::string PowerHintSession::getIdString() const {
std::string idstr = StringPrintf("%" PRId32 "-%" PRId32 "-%" PRIxPTR, mDescriptor->tgid,
mDescriptor->uid, reinterpret_cast<uintptr_t>(this) & 0xffff);
return idstr;
} }
bool PowerHintSession::isAppSession() { bool PowerHintSession::isAppSession() {
// Check if uid is in range reserved for applications // Check if uid is in range reserved for applications
return mDescriptor->uid >= AID_APP_START; return mDescriptor->uid >= AID_APP_START;
} }
void PowerHintSession::updateUniveralBoostMode() { void PowerHintSession::updateUniveralBoostMode() {
if (!isAppSession()) { if (!isAppSession()) {
return; return;
} }
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
const std::string tag = StringPrintf("%s:updateUniveralBoostMode()", mIdString.c_str()); const std::string tag = StringPrintf("%s:updateUniveralBoostMode()", getIdString().c_str());
ATRACE_BEGIN(tag.c_str()); ATRACE_BEGIN(tag.c_str());
} }
PowerHintMonitor::getInstance()->getLooper()->sendMessage(mPowerManagerHandler, NULL); PowerHintMonitor::getInstance()->getLooper()->sendMessage(mPowerManagerHandler, NULL);
@ -150,14 +190,7 @@ void PowerHintSession::updateUniveralBoostMode() {
ATRACE_END(); ATRACE_END();
} }
} }
void PowerHintSession::tryToSendPowerHint(std::string hint) {
if (!mSupportedHints[hint].has_value()) {
mSupportedHints[hint] = HintManager::GetInstance()->IsHintSupported(hint);
}
if (mSupportedHints[hint].value()) {
HintManager::GetInstance()->DoHint(hint);
}
}
int PowerHintSession::setSessionUclampMin(int32_t min) { int PowerHintSession::setSessionUclampMin(int32_t min) {
{ {
std::lock_guard<std::mutex> guard(mSessionLock); std::lock_guard<std::mutex> guard(mSessionLock);
@ -167,20 +200,26 @@ int PowerHintSession::setSessionUclampMin(int32_t min) {
mStaleTimerHandler->updateTimer(); mStaleTimerHandler->updateTimer();
} }
PowerSessionManager::getInstance()->setUclampMin(this, min); PowerSessionManager::getInstance()->setUclampMin(this, min);
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("min", min); const std::string idstr = getIdString();
std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
ATRACE_INT(sz.c_str(), min);
} }
return 0; return 0;
} }
int PowerHintSession::getUclampMin() { int PowerHintSession::getUclampMin() {
return mDescriptor->current_min; return mDescriptor->current_min;
} }
void PowerHintSession::dumpToStream(std::ostream &stream) { void PowerHintSession::dumpToStream(std::ostream &stream) {
stream << "ID.Min.Act.Timeout(" << mIdString; stream << "ID.Min.Act.Timeout(" << getIdString();
stream << ", " << mDescriptor->current_min; stream << ", " << mDescriptor->current_min;
stream << ", " << mDescriptor->is_active; stream << ", " << mDescriptor->is_active;
stream << ", " << isTimeout() << ")"; stream << ", " << isTimeout() << ")";
} }
ndk::ScopedAStatus PowerHintSession::pause() { ndk::ScopedAStatus PowerHintSession::pause() {
if (mSessionClosed) { if (mSessionClosed) {
ALOGE("Error: session is dead"); ALOGE("Error: session is dead");
@ -192,11 +231,14 @@ ndk::ScopedAStatus PowerHintSession::pause() {
mDescriptor->is_active.store(false); mDescriptor->is_active.store(false);
setStale(); setStale();
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("active", mDescriptor->is_active.load()); const std::string idstr = getIdString();
std::string sz = StringPrintf("adpf.%s-active", idstr.c_str());
ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
} }
updateUniveralBoostMode(); updateUniveralBoostMode();
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus PowerHintSession::resume() { ndk::ScopedAStatus PowerHintSession::resume() {
if (mSessionClosed) { if (mSessionClosed) {
ALOGE("Error: session is dead"); ALOGE("Error: session is dead");
@ -208,11 +250,14 @@ ndk::ScopedAStatus PowerHintSession::resume() {
// resume boost // resume boost
setSessionUclampMin(mDescriptor->current_min); setSessionUclampMin(mDescriptor->current_min);
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("active", mDescriptor->is_active.load()); const std::string idstr = getIdString();
std::string sz = StringPrintf("adpf.%s-active", idstr.c_str());
ATRACE_INT(sz.c_str(), mDescriptor->is_active.load());
} }
updateUniveralBoostMode(); updateUniveralBoostMode();
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus PowerHintSession::close() { ndk::ScopedAStatus PowerHintSession::close() {
bool sessionClosedExpectedToBe = false; bool sessionClosedExpectedToBe = false;
if (!mSessionClosed.compare_exchange_strong(sessionClosedExpectedToBe, true)) { if (!mSessionClosed.compare_exchange_strong(sessionClosedExpectedToBe, true)) {
@ -220,12 +265,18 @@ ndk::ScopedAStatus PowerHintSession::close() {
} }
// Remove the session from PowerSessionManager first to avoid racing. // Remove the session from PowerSessionManager first to avoid racing.
PowerSessionManager::getInstance()->removePowerSession(this); PowerSessionManager::getInstance()->removePowerSession(this);
mStaleTimerHandler->setSessionDead();
setSessionUclampMin(0); setSessionUclampMin(0);
{
std::lock_guard<std::mutex> guard(mSessionLock);
mSessionClosed.store(true);
}
mDescriptor->is_active.store(false); mDescriptor->is_active.store(false);
mEarlyBoostHandler->setSessionDead();
mStaleTimerHandler->setSessionDead();
updateUniveralBoostMode(); updateUniveralBoostMode();
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus PowerHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) { ndk::ScopedAStatus PowerHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) {
if (mSessionClosed) { if (mSessionClosed) {
ALOGE("Error: session is dead"); ALOGE("Error: session is dead");
@ -238,12 +289,17 @@ ndk::ScopedAStatus PowerHintSession::updateTargetWorkDuration(int64_t targetDura
targetDurationNanos = targetDurationNanos =
targetDurationNanos * HintManager::GetInstance()->GetAdpfProfile()->mTargetTimeFactor; targetDurationNanos * HintManager::GetInstance()->GetAdpfProfile()->mTargetTimeFactor;
ALOGV("update target duration: %" PRId64 " ns", targetDurationNanos); ALOGV("update target duration: %" PRId64 " ns", targetDurationNanos);
mDescriptor->duration = std::chrono::nanoseconds(targetDurationNanos); mDescriptor->duration = std::chrono::nanoseconds(targetDurationNanos);
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("target", mDescriptor->duration.count()); const std::string idstr = getIdString();
std::string sz = StringPrintf("adpf.%s-target", idstr.c_str());
ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
} }
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration( ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration(
const std::vector<WorkDuration> &actualDurations) { const std::vector<WorkDuration> &actualDurations) {
if (mSessionClosed) { if (mSessionClosed) {
@ -266,33 +322,49 @@ ndk::ScopedAStatus PowerHintSession::reportActualWorkDuration(
mDescriptor->update_count++; mDescriptor->update_count++;
bool isFirstFrame = isTimeout(); bool isFirstFrame = isTimeout();
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("batch_size", actualDurations.size()); const std::string idstr = getIdString();
traceSessionVal("actl_last", actualDurations.back().durationNanos); std::string sz = StringPrintf("adpf.%s-batch_size", idstr.c_str());
traceSessionVal("target", mDescriptor->duration.count()); ATRACE_INT(sz.c_str(), actualDurations.size());
traceSessionVal("hint.count", mDescriptor->update_count); sz = StringPrintf("adpf.%s-actl_last", idstr.c_str());
traceSessionVal("hint.overtime", ATRACE_INT(sz.c_str(), actualDurations.back().durationNanos);
sz = StringPrintf("adpf.%s-target", idstr.c_str());
ATRACE_INT(sz.c_str(), (int64_t)mDescriptor->duration.count());
sz = StringPrintf("adpf.%s-hint.count", idstr.c_str());
ATRACE_INT(sz.c_str(), mDescriptor->update_count);
sz = StringPrintf("adpf.%s-hint.overtime", idstr.c_str());
ATRACE_INT(sz.c_str(),
actualDurations.back().durationNanos - mDescriptor->duration.count() > 0); actualDurations.back().durationNanos - mDescriptor->duration.count() > 0);
traceSessionVal("session_hint", -1);
} }
mLastUpdatedTime.store(std::chrono::steady_clock::now()); mLastUpdatedTime.store(std::chrono::steady_clock::now());
if (isFirstFrame) { if (isFirstFrame) {
if (isAppSession()) {
tryToSendPowerHint("ADPF_FIRST_FRAME");
}
updateUniveralBoostMode(); updateUniveralBoostMode();
} }
if (!adpfConfig->mPidOn) { if (!adpfConfig->mPidOn) {
setSessionUclampMin(adpfConfig->mUclampMinHigh); setSessionUclampMin(adpfConfig->mUclampMinHigh);
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
int64_t output = convertWorkDurationToBoostByPid(actualDurations); int64_t output = convertWorkDurationToBoostByPid(
adpfConfig, mDescriptor->duration, actualDurations, &(mDescriptor->integral_error),
&(mDescriptor->previous_error), getIdString());
/* apply to all the threads in the group */ /* apply to all the threads in the group */
int next_min = std::min(static_cast<int>(adpfConfig->mUclampMinHigh), int next_min = std::min(static_cast<int>(adpfConfig->mUclampMinHigh),
mDescriptor->current_min + static_cast<int>(output)); mDescriptor->current_min + static_cast<int>(output));
next_min = std::max(static_cast<int>(adpfConfig->mUclampMinLow), next_min); next_min = std::max(static_cast<int>(adpfConfig->mUclampMinLow), next_min);
setSessionUclampMin(next_min); setSessionUclampMin(next_min);
mStaleTimerHandler->updateTimer(getStaleTime());
if (HintManager::GetInstance()->GetAdpfProfile()->mEarlyBoostOn) {
updateWorkPeriod(actualDurations);
mEarlyBoostHandler->updateTimer(getEarlyBoostTime());
}
mAdaptiveCpu->ReportWorkDurations(actualDurations, mDescriptor->duration);
return ndk::ScopedAStatus::ok(); return ndk::ScopedAStatus::ok();
} }
std::string AppHintDesc::toString() const { std::string AppHintDesc::toString() const {
std::string out = std::string out =
StringPrintf("session %" PRIxPTR "\n", reinterpret_cast<uintptr_t>(this) & 0xffff); StringPrintf("session %" PRIxPTR "\n", reinterpret_cast<uintptr_t>(this) & 0xffff);
@ -300,6 +372,7 @@ std::string AppHintDesc::toString() const {
out.append(StringPrintf(" duration: %" PRId64 " ns\n", durationNanos)); out.append(StringPrintf(" duration: %" PRId64 " ns\n", durationNanos));
out.append(StringPrintf(" uclamp.min: %d \n", current_min)); out.append(StringPrintf(" uclamp.min: %d \n", current_min));
out.append(StringPrintf(" uid: %d, tgid: %d\n", uid, tgid)); out.append(StringPrintf(" uid: %d, tgid: %d\n", uid, tgid));
out.append(" threadIds: ["); out.append(" threadIds: [");
bool first = true; bool first = true;
for (int tid : threadIds) { for (int tid : threadIds) {
@ -312,49 +385,121 @@ std::string AppHintDesc::toString() const {
out.append("]\n"); out.append("]\n");
return out; return out;
} }
bool PowerHintSession::isActive() { bool PowerHintSession::isActive() {
return mDescriptor->is_active.load(); return mDescriptor->is_active.load();
} }
bool PowerHintSession::isTimeout() { bool PowerHintSession::isTimeout() {
auto now = std::chrono::steady_clock::now(); auto now = std::chrono::steady_clock::now();
time_point<steady_clock> staleTime = return now >= getStaleTime();
mLastUpdatedTime.load() +
nanoseconds(static_cast<int64_t>(
mDescriptor->duration.count() *
HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor));
return now >= staleTime;
} }
const std::vector<int> &PowerHintSession::getTidList() const { const std::vector<int> &PowerHintSession::getTidList() const {
return mDescriptor->threadIds; return mDescriptor->threadIds;
} }
void PowerHintSession::setStale() { void PowerHintSession::setStale() {
// Reset to default uclamp value. // Reset to default uclamp value.
PowerSessionManager::getInstance()->setUclampMin(this, 0); PowerSessionManager::getInstance()->setUclampMin(this, 0);
// Deliver a task to check if all sessions are inactive. // Deliver a task to check if all sessions are inactive.
updateUniveralBoostMode(); updateUniveralBoostMode();
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
traceSessionVal("min", 0); const std::string idstr = getIdString();
std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
ATRACE_INT(sz.c_str(), 0);
} }
} }
void PowerHintSession::StaleTimerHandler::updateTimer() {
auto now = std::chrono::steady_clock::now(); void PowerHintSession::wakeup() {
nanoseconds staleDuration = std::chrono::nanoseconds( std::lock_guard<std::mutex> guard(mSessionLock);
static_cast<int64_t>(mSession->mDescriptor->duration.count() *
// We only wake up non-paused and stale sessions
if (mSessionClosed || !isActive() || !isTimeout())
return;
if (ATRACE_ENABLED()) {
std::string tag = StringPrintf("wakeup.%s(a:%d,s:%d)", getIdString().c_str(), isActive(),
isTimeout());
ATRACE_NAME(tag.c_str());
}
std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
int min = std::max(mDescriptor->current_min, static_cast<int>(adpfConfig->mUclampMinInit));
mDescriptor->current_min = min;
PowerSessionManager::getInstance()->setUclampMinLocked(this, min);
mStaleTimerHandler->updateTimer();
if (ATRACE_ENABLED()) {
const std::string idstr = getIdString();
std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
ATRACE_INT(sz.c_str(), min);
}
}
void PowerHintSession::updateWorkPeriod(const std::vector<WorkDuration> &actualDurations) {
if (actualDurations.size() == 0)
return;
if (actualDurations.size() >= 2) {
const WorkDuration &last = actualDurations[actualDurations.size() - 2];
mLastStartedTimeNs = last.timeStampNanos - last.durationNanos;
}
const WorkDuration &current = actualDurations.back();
int64_t curr_start = current.timeStampNanos - current.durationNanos;
int64_t period = curr_start - mLastStartedTimeNs;
if (period > 0 && period < mDescriptor->duration.count() * 2) {
// Accounting workload period with moving average for the last 10 workload.
mWorkPeriodNs = 0.9 * mWorkPeriodNs + 0.1 * period;
if (ATRACE_ENABLED()) {
const std::string idstr = getIdString();
std::string sz = StringPrintf("adpf.%s-timer.period", idstr.c_str());
ATRACE_INT(sz.c_str(), mWorkPeriodNs);
}
}
mLastStartedTimeNs = curr_start;
mLastDurationNs = current.durationNanos;
}
time_point<steady_clock> PowerHintSession::getEarlyBoostTime() {
std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
int64_t earlyBoostTimeoutNs =
(int64_t)mDescriptor->duration.count() * adpfConfig->mEarlyBoostTimeFactor;
time_point<steady_clock> nextStartTime =
mLastUpdatedTime.load() + nanoseconds(mWorkPeriodNs - mLastDurationNs);
return nextStartTime + nanoseconds(earlyBoostTimeoutNs);
}
time_point<steady_clock> PowerHintSession::getStaleTime() {
return mLastUpdatedTime.load() +
nanoseconds(static_cast<int64_t>(
mDescriptor->duration.count() *
HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor)); HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor));
mStaleTime.store(now + staleDuration); }
int64_t next = static_cast<int64_t>(staleDuration.count());
void PowerHintSession::StaleTimerHandler::updateTimer() {
time_point<steady_clock> staleTime =
std::chrono::steady_clock::now() +
nanoseconds(static_cast<int64_t>(
mSession->mDescriptor->duration.count() *
HintManager::GetInstance()->GetAdpfProfile()->mStaleTimeFactor));
updateTimer(staleTime);
}
void PowerHintSession::StaleTimerHandler::updateTimer(time_point<steady_clock> staleTime) {
mStaleTime.store(staleTime);
{ {
std::lock_guard<std::mutex> guard(mMessageLock); std::lock_guard<std::mutex> guard(mMessageLock);
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler); PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler);
PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed( PowerHintMonitor::getInstance()->getLooper()->sendMessage(mSession->mStaleTimerHandler,
next, mSession->mStaleTimerHandler, NULL); NULL);
} }
mIsMonitoring.store(true);
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
mSession->traceSessionVal("timer.stale", 0); const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-timer.stale", idstr.c_str());
ATRACE_INT(sz.c_str(), 0);
} }
} }
void PowerHintSession::StaleTimerHandler::handleMessage(const Message &) { void PowerHintSession::StaleTimerHandler::handleMessage(const Message &) {
std::lock_guard<std::mutex> guard(mClosedLock);
if (mIsSessionDead) { if (mIsSessionDead) {
return; return;
} }
@ -369,19 +514,80 @@ void PowerHintSession::StaleTimerHandler::handleMessage(const Message &) {
next, mSession->mStaleTimerHandler, NULL); next, mSession->mStaleTimerHandler, NULL);
} else { } else {
mSession->setStale(); mSession->setStale();
mIsMonitoring.store(false);
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
mSession->traceSessionVal("session_hint", -1); const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
ATRACE_INT(sz.c_str(), 0);
} }
} }
if (ATRACE_ENABLED()) { if (ATRACE_ENABLED()) {
mSession->traceSessionVal("timer.stale", next > 0 ? 0 : 1); const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-timer.stale", idstr.c_str());
ATRACE_INT(sz.c_str(), mIsMonitoring ? 0 : 1);
} }
} }
void PowerHintSession::StaleTimerHandler::setSessionDead() { void PowerHintSession::StaleTimerHandler::setSessionDead() {
std::lock_guard<std::mutex> guard(mClosedLock); std::lock_guard<std::mutex> guard(mStaleLock);
mIsSessionDead = true; mIsSessionDead = true;
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler); PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mStaleTimerHandler);
} }
void PowerHintSession::EarlyBoostHandler::updateTimer(time_point<steady_clock> boostTime) {
mBoostTime.store(boostTime);
{
std::lock_guard<std::mutex> guard(mMessageLock);
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
PowerHintMonitor::getInstance()->getLooper()->sendMessage(mSession->mEarlyBoostHandler,
NULL);
}
mIsMonitoring.store(true);
if (ATRACE_ENABLED()) {
const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
ATRACE_INT(sz.c_str(), 1);
}
}
void PowerHintSession::EarlyBoostHandler::handleMessage(const Message &) {
std::lock_guard<std::mutex> guard(mBoostLock);
if (mIsSessionDead) {
return;
}
auto now = std::chrono::steady_clock::now();
int64_t next =
static_cast<int64_t>(duration_cast<nanoseconds>(mBoostTime.load() - now).count());
if (next > 0) {
if (ATRACE_ENABLED()) {
const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
ATRACE_INT(sz.c_str(), 1);
}
std::lock_guard<std::mutex> guard(mMessageLock);
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
PowerHintMonitor::getInstance()->getLooper()->sendMessageDelayed(
next, mSession->mEarlyBoostHandler, NULL);
} else {
std::shared_ptr<AdpfConfig> adpfConfig = HintManager::GetInstance()->GetAdpfProfile();
PowerSessionManager::getInstance()->setUclampMin(mSession, adpfConfig->mUclampMinHigh);
mIsMonitoring.store(false);
if (ATRACE_ENABLED()) {
const std::string idstr = mSession->getIdString();
std::string sz = StringPrintf("adpf.%s-min", idstr.c_str());
ATRACE_INT(sz.c_str(), adpfConfig->mUclampMinHigh);
sz = StringPrintf("adpf.%s-timer.earlyboost", idstr.c_str());
ATRACE_INT(sz.c_str(), 2);
}
}
}
void PowerHintSession::EarlyBoostHandler::setSessionDead() {
std::lock_guard<std::mutex> guard(mBoostLock);
mIsSessionDead = true;
PowerHintMonitor::getInstance()->getLooper()->removeMessages(mSession->mEarlyBoostHandler);
}
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -13,19 +13,26 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <aidl/android/hardware/power/BnPowerHintSession.h> #include <aidl/android/hardware/power/BnPowerHintSession.h>
#include <aidl/android/hardware/power/WorkDuration.h> #include <aidl/android/hardware/power/WorkDuration.h>
#include <utils/Looper.h> #include <utils/Looper.h>
#include <utils/Thread.h> #include <utils/Thread.h>
#include <mutex> #include <mutex>
#include <unordered_map> #include <unordered_map>
#include "adaptivecpu/AdaptiveCpu.h"
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
using aidl::android::hardware::power::BnPowerHintSession; using aidl::android::hardware::power::BnPowerHintSession;
using aidl::android::hardware::power::WorkDuration; using aidl::android::hardware::power::WorkDuration;
using ::android::Message; using ::android::Message;
@ -35,6 +42,7 @@ using std::chrono::milliseconds;
using std::chrono::nanoseconds; using std::chrono::nanoseconds;
using std::chrono::steady_clock; using std::chrono::steady_clock;
using std::chrono::time_point; using std::chrono::time_point;
struct AppHintDesc { struct AppHintDesc {
AppHintDesc(int32_t tgid, int32_t uid, std::vector<int> threadIds) AppHintDesc(int32_t tgid, int32_t uid, std::vector<int> threadIds)
: tgid(tgid), : tgid(tgid),
@ -59,10 +67,11 @@ struct AppHintDesc {
int64_t integral_error; int64_t integral_error;
int64_t previous_error; int64_t previous_error;
}; };
class PowerHintSession : public BnPowerHintSession { class PowerHintSession : public BnPowerHintSession {
public: public:
explicit PowerHintSession(int32_t tgid, int32_t uid, const std::vector<int32_t> &threadIds, explicit PowerHintSession(std::shared_ptr<AdaptiveCpu> adaptiveCpu, int32_t tgid, int32_t uid,
int64_t durationNanos); const std::vector<int32_t> &threadIds, int64_t durationNanos);
~PowerHintSession(); ~PowerHintSession();
ndk::ScopedAStatus close() override; ndk::ScopedAStatus close() override;
ndk::ScopedAStatus pause() override; ndk::ScopedAStatus pause() override;
@ -72,43 +81,72 @@ class PowerHintSession : public BnPowerHintSession {
const std::vector<WorkDuration> &actualDurations) override; const std::vector<WorkDuration> &actualDurations) override;
bool isActive(); bool isActive();
bool isTimeout(); bool isTimeout();
void wakeup();
void setStale(); void setStale();
// Is this hint session for a user application // Is this hint session for a user application
bool isAppSession(); bool isAppSession();
const std::vector<int> &getTidList() const; const std::vector<int> &getTidList() const;
int getUclampMin(); int getUclampMin();
void dumpToStream(std::ostream &stream); void dumpToStream(std::ostream &stream);
void updateWorkPeriod(const std::vector<WorkDuration> &actualDurations);
time_point<steady_clock> getEarlyBoostTime();
time_point<steady_clock> getStaleTime(); time_point<steady_clock> getStaleTime();
private: private:
class StaleTimerHandler : public MessageHandler { class StaleTimerHandler : public MessageHandler {
public: public:
StaleTimerHandler(PowerHintSession *session) : mSession(session), mIsSessionDead(false) {} StaleTimerHandler(PowerHintSession *session)
: mSession(session), mIsMonitoring(false), mIsSessionDead(false) {}
void updateTimer(); void updateTimer();
void updateTimer(time_point<steady_clock> staleTime);
void handleMessage(const Message &message) override; void handleMessage(const Message &message) override;
void setSessionDead(); void setSessionDead();
private: private:
PowerHintSession *mSession; PowerHintSession *mSession;
std::mutex mClosedLock; std::mutex mStaleLock;
std::mutex mMessageLock; std::mutex mMessageLock;
std::atomic<time_point<steady_clock>> mStaleTime; std::atomic<time_point<steady_clock>> mStaleTime;
std::atomic<bool> mIsMonitoring;
bool mIsSessionDead; bool mIsSessionDead;
}; };
class EarlyBoostHandler : public MessageHandler {
public:
EarlyBoostHandler(PowerHintSession *session)
: mSession(session), mIsMonitoring(false), mIsSessionDead(false) {}
void updateTimer(time_point<steady_clock> boostTime);
void handleMessage(const Message &message) override;
void setSessionDead();
private:
PowerHintSession *mSession;
std::mutex mBoostLock;
std::mutex mMessageLock;
std::atomic<time_point<steady_clock>> mBoostTime;
std::atomic<bool> mIsMonitoring;
bool mIsSessionDead;
};
private: private:
void updateUniveralBoostMode(); void updateUniveralBoostMode();
int setSessionUclampMin(int32_t min); int setSessionUclampMin(int32_t min);
void tryToSendPowerHint(std::string hint); std::string getIdString() const;
int64_t convertWorkDurationToBoostByPid(const std::vector<WorkDuration> &actualDurations); const std::shared_ptr<AdaptiveCpu> mAdaptiveCpu;
void traceSessionVal(char const *identifier, int64_t val) const;
AppHintDesc *mDescriptor = nullptr; AppHintDesc *mDescriptor = nullptr;
sp<StaleTimerHandler> mStaleTimerHandler; sp<StaleTimerHandler> mStaleTimerHandler;
sp<EarlyBoostHandler> mEarlyBoostHandler;
std::atomic<time_point<steady_clock>> mLastUpdatedTime; std::atomic<time_point<steady_clock>> mLastUpdatedTime;
sp<MessageHandler> mPowerManagerHandler; sp<MessageHandler> mPowerManagerHandler;
std::mutex mSessionLock; std::mutex mSessionLock;
std::atomic<bool> mSessionClosed = false; std::atomic<bool> mSessionClosed = false;
std::string mIdString; // These 3 variables are for earlyboost work period estimation.
// To cache the status of whether ADPF hints are supported. int64_t mLastStartedTimeNs;
std::unordered_map<std::string, std::optional<bool>> mSupportedHints; int64_t mLastDurationNs;
int64_t mWorkPeriodNs;
}; };
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -13,23 +13,28 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#define LOG_TAG "powerhal-libperfmgr" #define LOG_TAG "powerhal-libperfmgr"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL) #define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "PowerSessionManager.h" #include "PowerSessionManager.h"
#include <android-base/file.h> #include <android-base/file.h>
#include <log/log.h> #include <log/log.h>
#include <perfmgr/HintManager.h> #include <perfmgr/HintManager.h>
#include <processgroup/processgroup.h> #include <processgroup/processgroup.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <utils/Trace.h> #include <utils/Trace.h>
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
using ::android::perfmgr::AdpfConfig;
using ::android::perfmgr::HintManager; using ::android::perfmgr::HintManager;
namespace { namespace {
/* there is no glibc or bionic wrapper */ /* there is no glibc or bionic wrapper */
struct sched_attr { struct sched_attr {
@ -44,6 +49,7 @@ struct sched_attr {
__u32 sched_util_min; __u32 sched_util_min;
__u32 sched_util_max; __u32 sched_util_max;
}; };
static int sched_setattr(int pid, struct sched_attr *attr, unsigned int flags) { static int sched_setattr(int pid, struct sched_attr *attr, unsigned int flags) {
if (!HintManager::GetInstance()->GetAdpfProfile()->mUclampMinOn) { if (!HintManager::GetInstance()->GetAdpfProfile()->mUclampMinOn) {
ALOGV("PowerSessionManager:%s: skip", __func__); ALOGV("PowerSessionManager:%s: skip", __func__);
@ -51,20 +57,25 @@ static int sched_setattr(int pid, struct sched_attr *attr, unsigned int flags) {
} }
return syscall(__NR_sched_setattr, pid, attr, flags); return syscall(__NR_sched_setattr, pid, attr, flags);
} }
static void set_uclamp_min(int tid, int min) { static void set_uclamp_min(int tid, int min) {
static constexpr int32_t kMaxUclampValue = 1024; static constexpr int32_t kMaxUclampValue = 1024;
min = std::max(0, min); min = std::max(0, min);
min = std::min(min, kMaxUclampValue); min = std::min(min, kMaxUclampValue);
sched_attr attr = {}; sched_attr attr = {};
attr.size = sizeof(attr); attr.size = sizeof(attr);
attr.sched_flags = (SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP_MIN); attr.sched_flags = (SCHED_FLAG_KEEP_ALL | SCHED_FLAG_UTIL_CLAMP_MIN);
attr.sched_util_min = min; attr.sched_util_min = min;
int ret = sched_setattr(tid, &attr, 0); int ret = sched_setattr(tid, &attr, 0);
if (ret) { if (ret) {
ALOGW("sched_setattr failed for thread %d, err=%d", tid, errno); ALOGW("sched_setattr failed for thread %d, err=%d", tid, errno);
} }
} }
} // namespace } // namespace
void PowerSessionManager::updateHintMode(const std::string &mode, bool enabled) { void PowerSessionManager::updateHintMode(const std::string &mode, bool enabled) {
ALOGV("PowerSessionManager::updateHintMode: mode: %s, enabled: %d", mode.c_str(), enabled); ALOGV("PowerSessionManager::updateHintMode: mode: %s, enabled: %d", mode.c_str(), enabled);
if (enabled && mode.compare(0, 8, "REFRESH_") == 0) { if (enabled && mode.compare(0, 8, "REFRESH_") == 0) {
@ -80,14 +91,27 @@ void PowerSessionManager::updateHintMode(const std::string &mode, bool enabled)
HintManager::GetInstance()->SetAdpfProfile(mode); HintManager::GetInstance()->SetAdpfProfile(mode);
} }
} }
void PowerSessionManager::updateHintBoost(const std::string &boost, int32_t durationMs) { void PowerSessionManager::updateHintBoost(const std::string &boost, int32_t durationMs) {
ATRACE_CALL(); ATRACE_CALL();
ALOGV("PowerSessionManager::updateHintBoost: boost: %s, durationMs: %d", boost.c_str(), ALOGV("PowerSessionManager::updateHintBoost: boost: %s, durationMs: %d", boost.c_str(),
durationMs); durationMs);
if (boost.compare("DISPLAY_UPDATE_IMMINENT") == 0) {
PowerHintMonitor::getInstance()->getLooper()->sendMessage(mWakeupHandler, NULL);
} }
}
void PowerSessionManager::wakeSessions() {
std::lock_guard<std::mutex> guard(mLock);
for (PowerHintSession *s : mSessions) {
s->wakeup();
}
}
int PowerSessionManager::getDisplayRefreshRate() { int PowerSessionManager::getDisplayRefreshRate() {
return mDisplayRefreshRate; return mDisplayRefreshRate;
} }
void PowerSessionManager::addPowerSession(PowerHintSession *session) { void PowerSessionManager::addPowerSession(PowerHintSession *session) {
std::lock_guard<std::mutex> guard(mLock); std::lock_guard<std::mutex> guard(mLock);
for (auto t : session->getTidList()) { for (auto t : session->getTidList()) {
@ -108,6 +132,7 @@ void PowerSessionManager::addPowerSession(PowerHintSession *session) {
} }
mSessions.insert(session); mSessions.insert(session);
} }
void PowerSessionManager::removePowerSession(PowerHintSession *session) { void PowerSessionManager::removePowerSession(PowerHintSession *session) {
std::lock_guard<std::mutex> guard(mLock); std::lock_guard<std::mutex> guard(mLock);
for (auto t : session->getTidList()) { for (auto t : session->getTidList()) {
@ -126,10 +151,12 @@ void PowerSessionManager::removePowerSession(PowerHintSession *session) {
} }
mSessions.erase(session); mSessions.erase(session);
} }
void PowerSessionManager::setUclampMin(PowerHintSession *session, int val) { void PowerSessionManager::setUclampMin(PowerHintSession *session, int val) {
std::lock_guard<std::mutex> guard(mLock); std::lock_guard<std::mutex> guard(mLock);
setUclampMinLocked(session, val); setUclampMinLocked(session, val);
} }
void PowerSessionManager::setUclampMinLocked(PowerHintSession *session, int val) { void PowerSessionManager::setUclampMinLocked(PowerHintSession *session, int val) {
for (auto t : session->getTidList()) { for (auto t : session->getTidList()) {
// Get thex max uclamp.min across sessions which include the tid. // Get thex max uclamp.min across sessions which include the tid.
@ -142,6 +169,7 @@ void PowerSessionManager::setUclampMinLocked(PowerHintSession *session, int val)
set_uclamp_min(t, std::max(val, tidMax)); set_uclamp_min(t, std::max(val, tidMax));
} }
} }
std::optional<bool> PowerSessionManager::isAnyAppSessionActive() { std::optional<bool> PowerSessionManager::isAnyAppSessionActive() {
std::lock_guard<std::mutex> guard(mLock); std::lock_guard<std::mutex> guard(mLock);
bool active = false; bool active = false;
@ -157,8 +185,10 @@ std::optional<bool> PowerSessionManager::isAnyAppSessionActive() {
} else { } else {
mActive = active; mActive = active;
} }
return active; return active;
} }
void PowerSessionManager::handleMessage(const Message &) { void PowerSessionManager::handleMessage(const Message &) {
auto active = isAnyAppSessionActive(); auto active = isAnyAppSessionActive();
if (!active.has_value()) { if (!active.has_value()) {
@ -170,6 +200,11 @@ void PowerSessionManager::handleMessage(const Message &) {
enableSystemTopAppBoost(); enableSystemTopAppBoost();
} }
} }
void PowerSessionManager::WakeupHandler::handleMessage(const Message &) {
PowerSessionManager::getInstance()->wakeSessions();
}
void PowerSessionManager::dumpToFd(int fd) { void PowerSessionManager::dumpToFd(int fd) {
std::ostringstream dump_buf; std::ostringstream dump_buf;
std::lock_guard<std::mutex> guard(mLock); std::lock_guard<std::mutex> guard(mLock);
@ -191,33 +226,39 @@ void PowerSessionManager::dumpToFd(int fd) {
ALOGE("Failed to dump one of session list to fd:%d", fd); ALOGE("Failed to dump one of session list to fd:%d", fd);
} }
} }
void PowerSessionManager::enableSystemTopAppBoost() { void PowerSessionManager::enableSystemTopAppBoost() {
if (HintManager::GetInstance()->IsHintSupported(kDisableBoostHintName)) { if (HintManager::GetInstance()->IsHintSupported(kDisableBoostHintName)) {
ALOGV("PowerSessionManager::enableSystemTopAppBoost!!"); ALOGV("PowerSessionManager::enableSystemTopAppBoost!!");
HintManager::GetInstance()->EndHint(kDisableBoostHintName); HintManager::GetInstance()->EndHint(kDisableBoostHintName);
} }
} }
void PowerSessionManager::disableSystemTopAppBoost() { void PowerSessionManager::disableSystemTopAppBoost() {
if (HintManager::GetInstance()->IsHintSupported(kDisableBoostHintName)) { if (HintManager::GetInstance()->IsHintSupported(kDisableBoostHintName)) {
ALOGV("PowerSessionManager::disableSystemTopAppBoost!!"); ALOGV("PowerSessionManager::disableSystemTopAppBoost!!");
HintManager::GetInstance()->DoHint(kDisableBoostHintName); HintManager::GetInstance()->DoHint(kDisableBoostHintName);
} }
} }
// =========== PowerHintMonitor implementation start from here =========== // =========== PowerHintMonitor implementation start from here ===========
void PowerHintMonitor::start() { void PowerHintMonitor::start() {
if (!isRunning()) { if (!isRunning()) {
run("PowerHintMonitor", ::android::PRIORITY_HIGHEST); run("PowerHintMonitor", ::android::PRIORITY_HIGHEST);
} }
} }
bool PowerHintMonitor::threadLoop() { bool PowerHintMonitor::threadLoop() {
while (true) { while (true) {
mLooper->pollOnce(-1); mLooper->pollOnce(-1);
} }
return true; return true;
} }
sp<Looper> PowerHintMonitor::getLooper() { sp<Looper> PowerHintMonitor::getLooper() {
return mLooper; return mLooper;
} }
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -13,26 +13,34 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <android-base/properties.h> #include <android-base/properties.h>
#include <perfmgr/HintManager.h> #include <perfmgr/HintManager.h>
#include <utils/Looper.h> #include <utils/Looper.h>
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <unordered_set> #include <unordered_set>
#include "PowerHintSession.h" #include "PowerHintSession.h"
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
using ::android::Looper; using ::android::Looper;
using ::android::Message; using ::android::Message;
using ::android::MessageHandler; using ::android::MessageHandler;
using ::android::Thread; using ::android::Thread;
using ::android::perfmgr::HintManager; using ::android::perfmgr::HintManager;
constexpr char kPowerHalAdpfDisableTopAppBoost[] = "vendor.powerhal.adpf.disable.hint"; constexpr char kPowerHalAdpfDisableTopAppBoost[] = "vendor.powerhal.adpf.disable.hint";
class PowerSessionManager : public MessageHandler { class PowerSessionManager : public MessageHandler {
public: public:
// current hint info // current hint info
@ -46,19 +54,31 @@ class PowerSessionManager : public MessageHandler {
void setUclampMinLocked(PowerHintSession *session, int min); void setUclampMinLocked(PowerHintSession *session, int min);
void handleMessage(const Message &message) override; void handleMessage(const Message &message) override;
void dumpToFd(int fd); void dumpToFd(int fd);
// Singleton // Singleton
static sp<PowerSessionManager> getInstance() { static sp<PowerSessionManager> getInstance() {
static sp<PowerSessionManager> instance = new PowerSessionManager(); static sp<PowerSessionManager> instance = new PowerSessionManager();
return instance; return instance;
} }
private: private:
class WakeupHandler : public MessageHandler {
public:
WakeupHandler() {}
void handleMessage(const Message &message) override;
};
private:
void wakeSessions();
std::optional<bool> isAnyAppSessionActive(); std::optional<bool> isAnyAppSessionActive();
void disableSystemTopAppBoost(); void disableSystemTopAppBoost();
void enableSystemTopAppBoost(); void enableSystemTopAppBoost();
const std::string kDisableBoostHintName; const std::string kDisableBoostHintName;
std::unordered_set<PowerHintSession *> mSessions; // protected by mLock std::unordered_set<PowerHintSession *> mSessions; // protected by mLock
std::unordered_map<int, int> mTidRefCountMap; // protected by mLock std::unordered_map<int, int> mTidRefCountMap; // protected by mLock
std::unordered_map<int, std::unordered_set<PowerHintSession *>> mTidSessionListMap; std::unordered_map<int, std::unordered_set<PowerHintSession *>> mTidSessionListMap;
sp<WakeupHandler> mWakeupHandler;
bool mActive; // protected by mLock bool mActive; // protected by mLock
/** /**
* mLock to pretect the above data objects opertions. * mLock to pretect the above data objects opertions.
@ -70,10 +90,13 @@ class PowerSessionManager : public MessageHandler {
: kDisableBoostHintName(::android::base::GetProperty(kPowerHalAdpfDisableTopAppBoost, : kDisableBoostHintName(::android::base::GetProperty(kPowerHalAdpfDisableTopAppBoost,
"ADPF_DISABLE_TA_BOOST")), "ADPF_DISABLE_TA_BOOST")),
mActive(false), mActive(false),
mDisplayRefreshRate(60) {} mDisplayRefreshRate(60) {
mWakeupHandler = sp<WakeupHandler>(new WakeupHandler());
}
PowerSessionManager(PowerSessionManager const &) = delete; PowerSessionManager(PowerSessionManager const &) = delete;
void operator=(PowerSessionManager const &) = delete; void operator=(PowerSessionManager const &) = delete;
}; };
class PowerHintMonitor : public Thread { class PowerHintMonitor : public Thread {
public: public:
void start(); void start();
@ -86,11 +109,13 @@ class PowerHintMonitor : public Thread {
} }
PowerHintMonitor(PowerHintMonitor const &) = delete; PowerHintMonitor(PowerHintMonitor const &) = delete;
void operator=(PowerHintMonitor const &) = delete; void operator=(PowerHintMonitor const &) = delete;
private: private:
sp<Looper> mLooper; sp<Looper> mLooper;
// Singleton // Singleton
PowerHintMonitor() : Thread(false), mLooper(new Looper(true)) {} PowerHintMonitor() : Thread(false), mLooper(new Looper(true)) {}
}; };
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -1,25 +1,32 @@
service vendor.power-hal-aidl /vendor/bin/hw/android.hardware.power-service.xiaomi-libperfmgr service vendor.power-hal-aidl /vendor/bin/hw/android.hardware.power-service.lenovo-sdm710-libperfmgr
class hal class hal
user root user root
group system group system
priority -20 priority -20
on late-fs on late-fs
start vendor.power-hal-aidl start vendor.power-hal-aidl
# Restart powerHAL when framework died # Restart powerHAL when framework died
on property:init.svc.zygote=restarting && property:vendor.powerhal.state=* on property:init.svc.zygote=restarting && property:vendor.powerhal.state=*
setprop vendor.powerhal.state "" setprop vendor.powerhal.state ""
setprop vendor.powerhal.audio "" setprop vendor.powerhal.audio ""
setprop vendor.powerhal.rendering "" setprop vendor.powerhal.rendering ""
restart vendor.power-hal-aidl restart vendor.power-hal-aidl
# Clean up after b/163539793 resolved # Clean up after b/163539793 resolved
on property:vendor.powerhal.dalvik.vm.dex2oat-threads=* on property:vendor.powerhal.dalvik.vm.dex2oat-threads=*
setprop dalvik.vm.dex2oat-threads ${vendor.powerhal.dalvik.vm.dex2oat-threads} setprop dalvik.vm.dex2oat-threads ${vendor.powerhal.dalvik.vm.dex2oat-threads}
setprop dalvik.vm.restore-dex2oat-threads ${vendor.powerhal.dalvik.vm.dex2oat-threads} setprop dalvik.vm.restore-dex2oat-threads ${vendor.powerhal.dalvik.vm.dex2oat-threads}
on property:vendor.powerhal.dalvik.vm.dex2oat-cpu-set=* on property:vendor.powerhal.dalvik.vm.dex2oat-cpu-set=*
setprop dalvik.vm.dex2oat-cpu-set ${vendor.powerhal.dalvik.vm.dex2oat-cpu-set} setprop dalvik.vm.dex2oat-cpu-set ${vendor.powerhal.dalvik.vm.dex2oat-cpu-set}
setprop dalvik.vm.restore-dex2oat-cpu-set ${vendor.powerhal.dalvik.vm.dex2oat-cpu-set} setprop dalvik.vm.restore-dex2oat-cpu-set ${vendor.powerhal.dalvik.vm.dex2oat-cpu-set}
# Restart powerHAL when debug property set # Restart powerHAL when debug property set
on property:ro.debuggable=1 && property:vendor.powerhal.config.debug=* on property:ro.debuggable=1 && property:vendor.powerhal.config.debug=*
restart vendor.power-hal-aidl restart vendor.power-hal-aidl
on property:persist.vendor.powerhal.config.debug=* on property:persist.vendor.powerhal.config.debug=*
setprop vendor.powerhal.config.debug ${persist.vendor.powerhal.config.debug} setprop vendor.powerhal.config.debug ${persist.vendor.powerhal.config.debug}

View file

@ -1,7 +1,7 @@
<manifest version="1.0" type="device"> <manifest version="1.0" type="device">
<hal format="aidl"> <hal format="aidl">
<name>android.hardware.power</name> <name>android.hardware.power</name>
<version>2</version> <version>3</version>
<fqname>IPower/default</fqname> <fqname>IPower/default</fqname>
</hal> </hal>
</manifest> </manifest>

View file

@ -0,0 +1,5 @@
BOARD_SEPOLICY_DIRS += hardware/google/pixel-sepolicy/power-libperfmgr
# power HAL
PRODUCT_PACKAGES += \
android.hardware.power-service.pixel-libperfmgr

View file

@ -13,55 +13,80 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#define LOG_TAG "powerhal-libperfmgr" #define LOG_TAG "powerhal-libperfmgr"
#include <android-base/logging.h> #include <android-base/logging.h>
#include <android-base/properties.h> #include <android-base/properties.h>
#include <android/binder_ibinder_platform.h> #include <android/binder_ibinder_platform.h>
#include <android/binder_manager.h> #include <android/binder_manager.h>
#include <android/binder_process.h> #include <android/binder_process.h>
#include <perfmgr/HintManager.h> #include <perfmgr/HintManager.h>
#include <thread> #include <thread>
#include "Power.h" #include "Power.h"
#include "PowerExt.h" #include "PowerExt.h"
#include "PowerSessionManager.h" #include "PowerSessionManager.h"
#include "adaptivecpu/AdaptiveCpu.h"
#include "disp-power/DisplayLowPower.h"
using aidl::google::hardware::power::impl::pixel::AdaptiveCpu;
using aidl::google::hardware::power::impl::pixel::DisplayLowPower;
using aidl::google::hardware::power::impl::pixel::Power; using aidl::google::hardware::power::impl::pixel::Power;
using aidl::google::hardware::power::impl::pixel::PowerExt; using aidl::google::hardware::power::impl::pixel::PowerExt;
using aidl::google::hardware::power::impl::pixel::PowerHintMonitor; using aidl::google::hardware::power::impl::pixel::PowerHintMonitor;
using aidl::google::hardware::power::impl::pixel::PowerSessionManager; using aidl::google::hardware::power::impl::pixel::PowerSessionManager;
using ::android::perfmgr::HintManager; using ::android::perfmgr::HintManager;
constexpr std::string_view kPowerHalInitProp("vendor.powerhal.init"); constexpr std::string_view kPowerHalInitProp("vendor.powerhal.init");
int main() { int main() {
// Parse config but do not start the looper // Parse config but do not start the looper
std::shared_ptr<HintManager> hm = std::shared_ptr<HintManager>(HintManager::GetInstance()); std::shared_ptr<HintManager> hm = HintManager::GetInstance();
if (!hm) { if (!hm) {
LOG(FATAL) << "HintManager Init failed"; LOG(FATAL) << "HintManager Init failed";
} }
std::shared_ptr<DisplayLowPower> dlpw = std::make_shared<DisplayLowPower>();
// single thread // single thread
ABinderProcess_setThreadPoolMaxThreadCount(0); ABinderProcess_setThreadPoolMaxThreadCount(0);
std::shared_ptr<AdaptiveCpu> adaptiveCpu = std::make_shared<AdaptiveCpu>();
// core service // core service
std::shared_ptr<Power> pw = ndk::SharedRefBase::make<Power>(); std::shared_ptr<Power> pw = ndk::SharedRefBase::make<Power>(dlpw, adaptiveCpu);
ndk::SpAIBinder pwBinder = pw->asBinder(); ndk::SpAIBinder pwBinder = pw->asBinder();
AIBinder_setMinSchedulerPolicy(pwBinder.get(), SCHED_NORMAL, -20); AIBinder_setMinSchedulerPolicy(pwBinder.get(), SCHED_NORMAL, -20);
// extension service // extension service
std::shared_ptr<PowerExt> pwExt = ndk::SharedRefBase::make<PowerExt>(); std::shared_ptr<PowerExt> pwExt = ndk::SharedRefBase::make<PowerExt>(dlpw, adaptiveCpu);
auto pwExtBinder = pwExt->asBinder(); auto pwExtBinder = pwExt->asBinder();
AIBinder_setMinSchedulerPolicy(pwExtBinder.get(), SCHED_NORMAL, -20); AIBinder_setMinSchedulerPolicy(pwExtBinder.get(), SCHED_NORMAL, -20);
// attach the extension to the same binder we will be registering // attach the extension to the same binder we will be registering
CHECK(STATUS_OK == AIBinder_setExtension(pwBinder.get(), pwExt->asBinder().get())); CHECK(STATUS_OK == AIBinder_setExtension(pwBinder.get(), pwExt->asBinder().get()));
const std::string instance = std::string() + Power::descriptor + "/default"; const std::string instance = std::string() + Power::descriptor + "/default";
binder_status_t status = AServiceManager_addService(pw->asBinder().get(), instance.c_str()); binder_status_t status = AServiceManager_addService(pw->asBinder().get(), instance.c_str());
CHECK(status == STATUS_OK); CHECK(status == STATUS_OK);
LOG(INFO) << "Xiaomi Power HAL AIDL Service with Extension is started."; LOG(INFO) << "Pixel Power HAL AIDL Service with Extension is started.";
if (HintManager::GetInstance()->GetAdpfProfile()) { if (HintManager::GetInstance()->GetAdpfProfile()) {
PowerHintMonitor::getInstance()->start(); PowerHintMonitor::getInstance()->start();
} }
std::thread initThread([&]() { std::thread initThread([&]() {
::android::base::WaitForProperty(kPowerHalInitProp.data(), "1"); ::android::base::WaitForProperty(kPowerHalInitProp.data(), "1");
HintManager::GetInstance()->Start(); HintManager::GetInstance()->Start();
dlpw->Init();
}); });
initThread.detach(); initThread.detach();
ABinderProcess_joinThreadPool(); ABinderProcess_joinThreadPool();
// should not reach // should not reach
LOG(ERROR) << "Xiaomi Power HAL AIDL Service with Extension just died."; LOG(ERROR) << "Pixel Power HAL AIDL Service with Extension just died.";
return EXIT_FAILURE; return EXIT_FAILURE;
} }

View file

@ -0,0 +1,87 @@
/*
* Copyright (C) 2020 The Android Open Source 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.
*/
#define LOG_TAG "powerhal-libperfmgr"
#include <errno.h>
#include <unistd.h>
#include <cutils/sockets.h>
#include <log/log.h>
#include "DisplayLowPower.h"
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
DisplayLowPower::DisplayLowPower() : mFossStatus(false) {}
void DisplayLowPower::Init() {
ConnectPpsDaemon();
}
void DisplayLowPower::SetDisplayLowPower(bool enable) {
SetFoss(enable);
}
void DisplayLowPower::ConnectPpsDaemon() {
constexpr const char kPpsDaemon[] = "pps";
mPpsSocket.reset(
socket_local_client(kPpsDaemon, ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM));
if (mPpsSocket.get() < 0) {
ALOGW("Connecting to PPS daemon failed (%s)", strerror(errno));
}
}
int DisplayLowPower::SendPpsCommand(const std::string_view cmd) {
if (TEMP_FAILURE_RETRY(write(mPpsSocket.get(), cmd.data(), cmd.size())) < 0) {
ALOGE("Failed to send pps command '%s' over socket (%s)", cmd.data(), strerror(errno));
return -1;
}
return 0;
}
void DisplayLowPower::SetFoss(bool enable) {
if (mPpsSocket.get() < 0 || mFossStatus == enable) {
return;
}
ALOGI("%s foss", (enable) ? "Enable" : "Disable");
std::string_view foss_cmd;
if (enable) {
foss_cmd = "foss:on";
} else {
foss_cmd = "foss:off";
}
if (!SendPpsCommand(foss_cmd)) {
mFossStatus = enable;
}
}
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -0,0 +1,51 @@
/*
* Copyright (C) 2020 The Android Open Source 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.
*/
#pragma once
#include <string_view>
#include <android-base/unique_fd.h>
namespace aidl {
namespace google {
namespace hardware {
namespace power {
namespace impl {
namespace pixel {
class DisplayLowPower {
public:
DisplayLowPower();
~DisplayLowPower() {}
void Init();
void SetDisplayLowPower(bool enable);
private:
void ConnectPpsDaemon();
int SendPpsCommand(const std::string_view cmd);
void SetFoss(bool enable);
::android::base::unique_fd mPpsSocket;
bool mFossStatus;
};
} // namespace pixel
} // namespace impl
} // namespace power
} // namespace hardware
} // namespace google
} // namespace aidl

View file

@ -13,9 +13,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#define LOG_TAG "powerhal-libperfmgr" #define LOG_TAG "powerhal-libperfmgr"
#define ATRACE_TAG (ATRACE_TAG_POWER | ATRACE_TAG_HAL)
#include "InteractionHandler.h" #include "InteractionHandler.h"
#include <android-base/properties.h> #include <android-base/properties.h>
#include <fcntl.h> #include <fcntl.h>
#include <perfmgr/HintManager.h> #include <perfmgr/HintManager.h>
@ -25,18 +28,24 @@
#include <unistd.h> #include <unistd.h>
#include <utils/Log.h> #include <utils/Log.h>
#include <utils/Trace.h> #include <utils/Trace.h>
#include <array> #include <array>
#include <memory> #include <memory>
#define MAX_LENGTH 64 #define MAX_LENGTH 64
#define MSINSEC 1000L #define MSINSEC 1000L
#define NSINMS 1000000L #define NSINMS 1000000L
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
namespace { namespace {
static const bool kDisplayIdleSupport = static const bool kDisplayIdleSupport =
::android::base::GetBoolProperty("vendor.powerhal.disp.idle_support", true); ::android::base::GetBoolProperty("vendor.powerhal.disp.idle_support", true);
static const std::array<const char *, 2> kDispIdlePath = {"/sys/class/drm/card0/device/idle_state", static const std::array<const char *, 2> kDispIdlePath = {"/sys/class/drm/card0/device/idle_state",
@ -49,12 +58,14 @@ static const uint32_t kMaxDurationMs =
::android::base::GetUintProperty("vendor.powerhal.interaction.max", /*default*/ 5650U); ::android::base::GetUintProperty("vendor.powerhal.interaction.max", /*default*/ 5650U);
static const uint32_t kDurationOffsetMs = static const uint32_t kDurationOffsetMs =
::android::base::GetUintProperty("vendor.powerhal.interaction.offset", /*default*/ 650U); ::android::base::GetUintProperty("vendor.powerhal.interaction.offset", /*default*/ 650U);
static size_t CalcTimespecDiffMs(struct timespec start, struct timespec end) { static size_t CalcTimespecDiffMs(struct timespec start, struct timespec end) {
size_t diff_in_ms = 0; size_t diff_in_ms = 0;
diff_in_ms += (end.tv_sec - start.tv_sec) * MSINSEC; diff_in_ms += (end.tv_sec - start.tv_sec) * MSINSEC;
diff_in_ms += (end.tv_nsec - start.tv_nsec) / NSINMS; diff_in_ms += (end.tv_nsec - start.tv_nsec) / NSINMS;
return diff_in_ms; return diff_in_ms;
} }
static int FbIdleOpen(void) { static int FbIdleOpen(void) {
int fd; int fd;
for (const auto &path : kDispIdlePath) { for (const auto &path : kDispIdlePath) {
@ -65,58 +76,77 @@ static int FbIdleOpen(void) {
ALOGE("Unable to open fb idle state path (%d)", errno); ALOGE("Unable to open fb idle state path (%d)", errno);
return -1; return -1;
} }
} // namespace } // namespace
using ::android::perfmgr::HintManager; using ::android::perfmgr::HintManager;
InteractionHandler::InteractionHandler() InteractionHandler::InteractionHandler()
: mState(INTERACTION_STATE_UNINITIALIZED), mDurationMs(0) {} : mState(INTERACTION_STATE_UNINITIALIZED), mDurationMs(0) {}
InteractionHandler::~InteractionHandler() { InteractionHandler::~InteractionHandler() {
Exit(); Exit();
} }
bool InteractionHandler::Init() { bool InteractionHandler::Init() {
std::lock_guard<std::mutex> lk(mLock); std::lock_guard<std::mutex> lk(mLock);
if (mState != INTERACTION_STATE_UNINITIALIZED) if (mState != INTERACTION_STATE_UNINITIALIZED)
return true; return true;
int fd = FbIdleOpen(); int fd = FbIdleOpen();
if (fd < 0) if (fd < 0)
return false; return false;
mIdleFd = fd; mIdleFd = fd;
mEventFd = eventfd(0, EFD_NONBLOCK); mEventFd = eventfd(0, EFD_NONBLOCK);
if (mEventFd < 0) { if (mEventFd < 0) {
ALOGE("Unable to create event fd (%d)", errno); ALOGE("Unable to create event fd (%d)", errno);
close(mIdleFd); close(mIdleFd);
return false; return false;
} }
mState = INTERACTION_STATE_IDLE; mState = INTERACTION_STATE_IDLE;
mThread = std::unique_ptr<std::thread>(new std::thread(&InteractionHandler::Routine, this)); mThread = std::unique_ptr<std::thread>(new std::thread(&InteractionHandler::Routine, this));
return true; return true;
} }
void InteractionHandler::Exit() { void InteractionHandler::Exit() {
std::unique_lock<std::mutex> lk(mLock); std::unique_lock<std::mutex> lk(mLock);
if (mState == INTERACTION_STATE_UNINITIALIZED) if (mState == INTERACTION_STATE_UNINITIALIZED)
return; return;
AbortWaitLocked(); AbortWaitLocked();
mState = INTERACTION_STATE_UNINITIALIZED; mState = INTERACTION_STATE_UNINITIALIZED;
lk.unlock(); lk.unlock();
mCond.notify_all(); mCond.notify_all();
mThread->join(); mThread->join();
close(mEventFd); close(mEventFd);
close(mIdleFd); close(mIdleFd);
} }
void InteractionHandler::PerfLock() { void InteractionHandler::PerfLock() {
ALOGV("%s: acquiring perf lock", __func__); ALOGV("%s: acquiring perf lock", __func__);
if (!HintManager::GetInstance()->DoHint("INTERACTION")) { if (!HintManager::GetInstance()->DoHint("INTERACTION")) {
ALOGE("%s: do hint INTERACTION failed", __func__); ALOGE("%s: do hint INTERACTION failed", __func__);
} }
} }
void InteractionHandler::PerfRel() { void InteractionHandler::PerfRel() {
ALOGV("%s: releasing perf lock", __func__); ALOGV("%s: releasing perf lock", __func__);
if (!HintManager::GetInstance()->EndHint("INTERACTION")) { if (!HintManager::GetInstance()->EndHint("INTERACTION")) {
ALOGE("%s: end hint INTERACTION failed", __func__); ALOGE("%s: end hint INTERACTION failed", __func__);
} }
} }
void InteractionHandler::Acquire(int32_t duration) { void InteractionHandler::Acquire(int32_t duration) {
ATRACE_CALL(); ATRACE_CALL();
std::lock_guard<std::mutex> lk(mLock); std::lock_guard<std::mutex> lk(mLock);
int inputDuration = duration + kDurationOffsetMs; int inputDuration = duration + kDurationOffsetMs;
int finalDuration; int finalDuration;
if (inputDuration > kMaxDurationMs) if (inputDuration > kMaxDurationMs)
@ -125,6 +155,7 @@ void InteractionHandler::Acquire(int32_t duration) {
finalDuration = inputDuration; finalDuration = inputDuration;
else else
finalDuration = kMinDurationMs; finalDuration = kMinDurationMs;
// Fallback to do boost directly // Fallback to do boost directly
// 1) override property is set OR // 1) override property is set OR
// 2) InteractionHandler not initialized // 2) InteractionHandler not initialized
@ -132,6 +163,7 @@ void InteractionHandler::Acquire(int32_t duration) {
HintManager::GetInstance()->DoHint("INTERACTION", std::chrono::milliseconds(finalDuration)); HintManager::GetInstance()->DoHint("INTERACTION", std::chrono::milliseconds(finalDuration));
return; return;
} }
struct timespec cur_timespec; struct timespec cur_timespec;
clock_gettime(CLOCK_MONOTONIC, &cur_timespec); clock_gettime(CLOCK_MONOTONIC, &cur_timespec);
if (mState != INTERACTION_STATE_IDLE && finalDuration <= mDurationMs) { if (mState != INTERACTION_STATE_IDLE && finalDuration <= mDurationMs) {
@ -146,14 +178,18 @@ void InteractionHandler::Acquire(int32_t duration) {
} }
mLastTimespec = cur_timespec; mLastTimespec = cur_timespec;
mDurationMs = finalDuration; mDurationMs = finalDuration;
ALOGV("%s: input: %d final duration: %d", __func__, duration, finalDuration); ALOGV("%s: input: %d final duration: %d", __func__, duration, finalDuration);
if (mState == INTERACTION_STATE_WAITING) if (mState == INTERACTION_STATE_WAITING)
AbortWaitLocked(); AbortWaitLocked();
else if (mState == INTERACTION_STATE_IDLE) else if (mState == INTERACTION_STATE_IDLE)
PerfLock(); PerfLock();
mState = INTERACTION_STATE_INTERACTION; mState = INTERACTION_STATE_INTERACTION;
mCond.notify_one(); mCond.notify_one();
} }
void InteractionHandler::Release() { void InteractionHandler::Release() {
std::lock_guard<std::mutex> lk(mLock); std::lock_guard<std::mutex> lk(mLock);
if (mState == INTERACTION_STATE_WAITING) { if (mState == INTERACTION_STATE_WAITING) {
@ -164,9 +200,11 @@ void InteractionHandler::Release() {
// clear any wait aborts pending in event fd // clear any wait aborts pending in event fd
uint64_t val; uint64_t val;
ssize_t ret = read(mEventFd, &val, sizeof(val)); ssize_t ret = read(mEventFd, &val, sizeof(val));
ALOGW_IF(ret < 0, "%s: failed to clear eventfd (%zd, %d)", __func__, ret, errno); ALOGW_IF(ret < 0, "%s: failed to clear eventfd (%zd, %d)", __func__, ret, errno);
} }
} }
// should be called while locked // should be called while locked
void InteractionHandler::AbortWaitLocked() { void InteractionHandler::AbortWaitLocked() {
uint64_t val = 1; uint64_t val = 1;
@ -174,16 +212,21 @@ void InteractionHandler::AbortWaitLocked() {
if (ret != sizeof(val)) if (ret != sizeof(val))
ALOGW("Unable to write to event fd (%zd)", ret); ALOGW("Unable to write to event fd (%zd)", ret);
} }
void InteractionHandler::WaitForIdle(int32_t wait_ms, int32_t timeout_ms) { void InteractionHandler::WaitForIdle(int32_t wait_ms, int32_t timeout_ms) {
char data[MAX_LENGTH]; char data[MAX_LENGTH];
ssize_t ret; ssize_t ret;
struct pollfd pfd[2]; struct pollfd pfd[2];
ATRACE_CALL(); ATRACE_CALL();
ALOGV("%s: wait:%d timeout:%d", __func__, wait_ms, timeout_ms); ALOGV("%s: wait:%d timeout:%d", __func__, wait_ms, timeout_ms);
pfd[0].fd = mEventFd; pfd[0].fd = mEventFd;
pfd[0].events = POLLIN; pfd[0].events = POLLIN;
pfd[1].fd = mIdleFd; pfd[1].fd = mIdleFd;
pfd[1].events = POLLPRI | POLLERR; pfd[1].events = POLLPRI | POLLERR;
ret = poll(pfd, 1, wait_ms); ret = poll(pfd, 1, wait_ms);
if (ret > 0) { if (ret > 0) {
ALOGV("%s: wait aborted", __func__); ALOGV("%s: wait aborted", __func__);
@ -192,15 +235,18 @@ void InteractionHandler::WaitForIdle(int32_t wait_ms, int32_t timeout_ms) {
ALOGE("%s: error in poll while waiting", __func__); ALOGE("%s: error in poll while waiting", __func__);
return; return;
} }
ret = pread(mIdleFd, data, sizeof(data), 0); ret = pread(mIdleFd, data, sizeof(data), 0);
if (!ret) { if (!ret) {
ALOGE("%s: Unexpected EOF!", __func__); ALOGE("%s: Unexpected EOF!", __func__);
return; return;
} }
if (!strncmp(data, "idle", 4)) { if (!strncmp(data, "idle", 4)) {
ALOGV("%s: already idle", __func__); ALOGV("%s: already idle", __func__);
return; return;
} }
ret = poll(pfd, 2, timeout_ms); ret = poll(pfd, 2, timeout_ms);
if (ret < 0) if (ret < 0)
ALOGE("%s: Error on waiting for idle (%zd)", __func__, ret); ALOGE("%s: Error on waiting for idle (%zd)", __func__, ret);
@ -211,9 +257,11 @@ void InteractionHandler::WaitForIdle(int32_t wait_ms, int32_t timeout_ms) {
else if (pfd[1].revents) else if (pfd[1].revents)
ALOGV("%s: idle detected", __func__); ALOGV("%s: idle detected", __func__);
} }
void InteractionHandler::Routine() { void InteractionHandler::Routine() {
pthread_setname_np(pthread_self(), "DispIdle"); pthread_setname_np(pthread_self(), "DispIdle");
std::unique_lock<std::mutex> lk(mLock, std::defer_lock); std::unique_lock<std::mutex> lk(mLock, std::defer_lock);
while (true) { while (true) {
lk.lock(); lk.lock();
mCond.wait(lk, [&] { return mState != INTERACTION_STATE_IDLE; }); mCond.wait(lk, [&] { return mState != INTERACTION_STATE_IDLE; });
@ -221,10 +269,12 @@ void InteractionHandler::Routine() {
return; return;
mState = INTERACTION_STATE_WAITING; mState = INTERACTION_STATE_WAITING;
lk.unlock(); lk.unlock();
WaitForIdle(kWaitMs, mDurationMs); WaitForIdle(kWaitMs, mDurationMs);
Release(); Release();
} }
} }
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -13,24 +13,29 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
#pragma once #pragma once
#include <condition_variable> #include <condition_variable>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <string> #include <string>
#include <thread> #include <thread>
namespace aidl { namespace aidl {
namespace google { namespace google {
namespace hardware { namespace hardware {
namespace power { namespace power {
namespace impl { namespace impl {
namespace pixel { namespace pixel {
enum InteractionState { enum InteractionState {
INTERACTION_STATE_UNINITIALIZED, INTERACTION_STATE_UNINITIALIZED,
INTERACTION_STATE_IDLE, INTERACTION_STATE_IDLE,
INTERACTION_STATE_INTERACTION, INTERACTION_STATE_INTERACTION,
INTERACTION_STATE_WAITING, INTERACTION_STATE_WAITING,
}; };
class InteractionHandler { class InteractionHandler {
public: public:
InteractionHandler(); InteractionHandler();
@ -38,13 +43,16 @@ class InteractionHandler {
bool Init(); bool Init();
void Exit(); void Exit();
void Acquire(int32_t duration); void Acquire(int32_t duration);
private: private:
void Release(); void Release();
void WaitForIdle(int32_t wait_ms, int32_t timeout_ms); void WaitForIdle(int32_t wait_ms, int32_t timeout_ms);
void AbortWaitLocked(); void AbortWaitLocked();
void Routine(); void Routine();
void PerfLock(); void PerfLock();
void PerfRel(); void PerfRel();
enum InteractionState mState; enum InteractionState mState;
int mIdleFd; int mIdleFd;
int mEventFd; int mEventFd;
@ -54,6 +62,7 @@ class InteractionHandler {
std::mutex mLock; std::mutex mLock;
std::condition_variable mCond; std::condition_variable mCond;
}; };
} // namespace pixel } // namespace pixel
} // namespace impl } // namespace impl
} // namespace power } // namespace power

View file

@ -6,6 +6,7 @@ persist.audio.fluence.voicecall=true
persist.audio.fluence.voicerec=false persist.audio.fluence.voicerec=false
persist.audio.fluence.speaker=true persist.audio.fluence.speaker=true
persist.audio.fluence.voicecomm=true persist.audio.fluence.voicecomm=true
persist.vendor.bt.a2dp_offload_cap=sbc-aptx-aptxhd-aac-ldac
ro.qc.sdk.audio.ssr=false ro.qc.sdk.audio.ssr=false
ro.qc.sdk.audio.fluencetype=none ro.qc.sdk.audio.fluencetype=none
@ -112,6 +113,3 @@ ro.zram.periodic_wb_delay_hours=24
# Zygote # Zygote
persist.device_config.runtime_native.usap_pool_enabled=true persist.device_config.runtime_native.usap_pool_enabled=true
# Radio
persist.vendor.qti.telephony.vt_cam_interface=2

View file

@ -444,16 +444,16 @@ vendor/lib64/vendor.qti.esepowermanager@1.0.so|a114629809e67015a14e5e367c6fb374a
vendor/lib64/vendor.qti.esepowermanager@1.1.so|f111cf42439d28fe88d9ebf6b6a1c44b729a3194 vendor/lib64/vendor.qti.esepowermanager@1.1.so|f111cf42439d28fe88d9ebf6b6a1c44b729a3194
# FM # FM
-product/lib/vendor.qti.hardware.fm@1.0.so:system_ext/lib/vendor.qti.hardware.fm@1.0.so lib64/fm_helium.so
-product/lib64/vendor.qti.hardware.fm@1.0.so:system_ext/lib64/vendor.qti.hardware.fm@1.0.so lib64/libfm-hci.so
system/lib/fm_helium.so:system_ext/lib/fm_helium.so lib/fm_helium.so
system/lib/libfm-hci.so:system_ext/lib/libfm-hci.so lib/libfm-hci.so
system/lib64/fm_helium.so:system_ext/lib64/fm_helium.so -product/lib64/vendor.qti.hardware.fm@1.0.so
system/lib64/libfm-hci.so:system_ext/lib64/libfm-hci.so -product/lib/vendor.qti.hardware.fm@1.0.so
vendor/lib/hw/vendor.qti.hardware.fm@1.0-impl.so
vendor/lib/vendor.qti.hardware.fm@1.0.so
vendor/lib64/hw/vendor.qti.hardware.fm@1.0-impl.so vendor/lib64/hw/vendor.qti.hardware.fm@1.0-impl.so
vendor/lib64/vendor.qti.hardware.fm@1.0.so vendor/lib64/vendor.qti.hardware.fm@1.0.so
vendor/lib/hw/vendor.qti.hardware.fm@1.0-impl.so
vendor/lib/vendor.qti.hardware.fm@1.0.so
# Gatekeeper # Gatekeeper
vendor/bin/hw/android.hardware.gatekeeper@1.0-service-qti vendor/bin/hw/android.hardware.gatekeeper@1.0-service-qti
@ -1006,53 +1006,67 @@ vendor/lib64/mediadrm/libwvdrmengine.so|f25fe9c6038fb99b0308998e0a8dba3b7c32fa50
vendor/lib64/libwvhidl.so|f32257498c35e1336b48a03463f8c8cea7df7b18 vendor/lib64/libwvhidl.so|f32257498c35e1336b48a03463f8c8cea7df7b18
vendor/lib/mediadrm/libwvdrmengine.so|0363a398d49518d0442df335e8cb7f19741dec9d vendor/lib/mediadrm/libwvdrmengine.so|0363a398d49518d0442df335e8cb7f19741dec9d
# WiFi Display (system) - from KB2001 14.0.0.81(EX01) # WiFi Display - from LA.QSSI.13.0.r1-05300-qssi.0
system/framework/WfdCommon.jar|a661c494d064b79a3f71579592411fada1ea232f -system/framework/WfdCommon.jar|9f431b56d7f38c71089333008695dd5f717e5034
system_ext/bin/wfdservice|400d123df78c1ed2e9643ff3ddf5ee5748f954fe system_ext/bin/wfdservice64|3326f77c84ac3b164d3ac4696292ad4ea9f20b72
system_ext/bin/wfdservice|cd0638589d1f652d5d40673105dd3ee63856cb88
system_ext/etc/init/wfdservice.rc|907def8565d8f91f531ca7dfad880af05d540b0c system_ext/etc/init/wfdservice.rc|907def8565d8f91f531ca7dfad880af05d540b0c
system_ext/etc/seccomp_policy/wfdservice.policy|5b3592c965f16b2d55ac89d56d8d3c49a6b5800b system_ext/etc/permissions/wfd-system-ext-privapp-permissions-qti.xml|828999946f9dfef98f17f42a1c8daba47c2c442d
system_ext/etc/seccomp_policy/wfdservice.policy|37994de64d6bd127898bd556cd614db459fe07ec
system_ext/etc/seccomp_policy/wfdservice64.policy|1e331272649395423b11c575892e0bdc9433b820
system_ext/etc/wfdconfigsink.xml|cb78df66948314a75080a4161321fb3111a0785a system_ext/etc/wfdconfigsink.xml|cb78df66948314a75080a4161321fb3111a0785a
system_ext/lib/com.qualcomm.qti.wifidisplayhal@1.0.so|cb88bc73bf9f44d7da000a41d38b309ffdf71370 system_ext/lib/com.qualcomm.qti.wifidisplayhal@1.0.so|146073f7288ee95dc5297d397e5199e5bc24e67d
system_ext/lib/libmmosal.so|e806f8040b4e59c6e08e437734a2176090a94ae3 system_ext/lib/libmiracastsystem.so|3b1caaa0b5f84e2c986af78a6a48e59d332282c4
system_ext/lib/libmmparser_lite.so|873d818fbfa0ce01a1f9cd951c1fba32d4159735 system_ext/lib/libmmosal.so|fc1359e5c79abf0bb877a652e6b900cef911e9dc
system_ext/lib/libmmrtpdecoder.so|4fc76315f11ff5fe416f36b66c9422ef05eae182 system_ext/lib/libmmparser_lite.so|7171defd018c507a2e34784569eb9920a22f15cf
system_ext/lib/libmmrtpencoder.so|0fa2096eec29eec395f6bd88d7d1049a127e090c system_ext/lib/libmmrtpdecoder.so|e15387b44fd9b3661d763d934663551ca30743d7
system_ext/lib/libwfdavenhancements.so|581db496334d2adb76e6c6af67620f49ca24eabd system_ext/lib/libmmrtpencoder.so|dbf276471b60a706d76e12edde388ef887b27396
system_ext/lib/libwfdclient.so|a9639d9f269880700bac6fc06e8302702fb0ab32 system_ext/lib/libwfdavenhancements.so|8a2eeeb2185b8b06aadeb11ec32141cea37cac9c
system_ext/lib/libwfdcommonutils.so|b738182e77f3e7faf72460f09ebdfca7de5e0c23 system_ext/lib/libwfdclient.so|feead7bcaf6a54b60a511f62fe2822a5ebf3fbee
system_ext/lib/libwfdconfigutils.so|df70b2da2b8aff916a1c2f6e7365d87cf1c4ffdf system_ext/lib/libwfdcommonutils.so|4b48d7941df68f7316c464d94d2f31d4e8f026e5
system_ext/lib/libwfddisplayconfig.so|f46fe63fb3d58c143dc92741a962167af3d8b928 system_ext/lib/libwfdconfigutils.so|2f6a16b597f814697d2ca1d92eab618b3e90ac9d
system_ext/lib/libwfdmminterface.so|5844114d7cc823090a70fe4f44cbda0ddf585ebd system_ext/lib/libwfddisplayconfig.so|ec3383d6c03a21985f4442eae6c7e935867d10c8
system_ext/lib/libwfdmmsink.so|23fb5c836fc06865b229c30b46998e41c0624dac system_ext/lib/libwfdmminterface.so|610a9dadc4f577a655b9fdfee2411a44b0e39a7d
system_ext/lib/libwfdmmsrc_system.so|0adfc69a5560158f3a6803ba720acc795d6d05dc system_ext/lib/libwfdmmsink.so|a045b3dd2b4cad52684e579af2d72554c178e9f6
system_ext/lib/libwfdrtsp.so|afd69963c2bd59bdb3ff23e01710c61ed90c5d87 system_ext/lib/libwfdmmsrc_system.so|c3a0c08eaefa1cb59ed3134752b9a6d424c0e1e6
system_ext/lib/libwfdservice.so|07e6d0e00393a8c068f75b46531d2e75fdaebde2 system_ext/lib/libwfdrtsp.so|3ace8ddfd6dc3f8aea2d8f489431599e6467de1c
system_ext/lib/libwfdsinksm.so|875171cc6ae534dd941eec1c87b78d5961e19c06 system_ext/lib/libwfdservice.so|1512125bbba762f3e5293a24ff13457a69597472
system_ext/lib/libwfduibcinterface.so|e90fa4920b010bd6ef2bd78c2d2644cbd0fcbffa system_ext/lib/libwfdsinksm.so|68d32947455c468d12e52a57cd71a2ba50d7fcd2
system_ext/lib/libwfduibcsink.so|91af548471c395a958e6155dd9be19cccbe482d3 system_ext/lib/libwfduibcinterface.so|7ac5b7fd7ff0b469629548549cf3a907068be174
system_ext/lib/libwfduibcsinkinterface.so|bc0e7dca28d1e5cbc6caf5bd5378f3e6db3b460c system_ext/lib/libwfduibcsink.so|5630028a8152379a1037d81224b8c031209b93ce
system_ext/lib/libwfduibcsrc.so|a0b1c73015c449468db0d2776fdfcc56dfeee53b system_ext/lib/libwfduibcsinkinterface.so|25e3cd7b8fd106c401597e9d71f47006ca06b31f
system_ext/lib/libwfduibcsrcinterface.so|2e24ec6a075407664488b4214eef35cb2ca845f4 system_ext/lib/libwfduibcsrc.so|09821648adb3275b2c2619af7581f35a47643ff5
system_ext/lib/vendor.qti.hardware.wifidisplaysession@1.0.so|45a0a8cd9f1aa5cbe69b113192d42bc42e32e9c3 system_ext/lib/libwfduibcsrcinterface.so|0c98741c0d65b27acf73a8b1a742e433fbeb86f4
system_ext/lib64/libmmosal.so|8488b27e6a9cda05c68181e8bf20afa7ba345222 system_ext/lib/vendor.qti.hardware.sigma_miracast@1.0-halimpl.so|6b274a507030e3b32c053a0eead50679c540448b
system_ext/lib64/libmmparser_lite.so|afd7b441e1bce732c14f5f8f49821d43bb2ee791 system_ext/lib/vendor.qti.hardware.sigma_miracast@1.0.so|c8c3d91a4732bee4c056f3af9bab89ac9622397c
system_ext/lib64/libmmrtpdecoder.so|0da526d51135ea58236ab6bcc2d1b7484931df24 system_ext/lib/vendor.qti.hardware.wifidisplaysession@1.0.so|d4e627158da501dd52f8936312f40364f480b1eb
system_ext/lib64/libmmrtpencoder.so|fafe00d1ed3d691c6d2c2d963144218764cad5ae system_ext/lib64/com.qualcomm.qti.wifidisplayhal@1.0.so|07a7c1f2f394d64b3683d318aa03bfacbe1e6784
system_ext/lib64/libwfdclient.so|0070b1e88cee6ebaf17dcb02c2706232cc087071 system_ext/lib64/libmiracastsystem.so|49385d8087da9b338b8a4ed99e5fa5cc0133c0b1
system_ext/lib64/libwfdcommonutils.so|14b3bd86703f2aca0abb1232d2304e626c1af644 system_ext/lib64/libmmosal.so|d46f10b470ecd829c6f2a424566f1cbbc6ebe234
system_ext/lib64/libwfdconfigutils.so|3b2d91fe7efefd81a0b5cdff59b9918c063fa7a9 system_ext/lib64/libmmparser_lite.so|1959f64d628f9c7dac476f4e32a4f9cae1443f76
system_ext/lib64/libwfddisplayconfig.so|5fd7bf7abaedfe890442f88183c49755b25c39aa system_ext/lib64/libmmrtpdecoder.so|8bb6d0a8f31795ed913acd3e8cb2299ada7cd22c
system_ext/lib64/libwfdmminterface.so|3f16acefbe87741a5841c1c70cf74ff917299c4c system_ext/lib64/libmmrtpencoder.so|fef79b731d9c2109f23ebc27575b6e057da8310f
system_ext/lib64/libwfdmmsink.so|8150b750357b606475521b491f78d566673f9888 system_ext/lib64/libwfdavenhancements.so|4906965cc3c3df4f1185cd63ae4f624666216b06
system_ext/lib64/libwfdnative.so|6d6dad5e631bc4d63463f608c47f3f9e5493944f system_ext/lib64/libwfdclient.so|09d0f04a6251f14f41e548592a9848af9d70975c
system_ext/lib64/libwfdrtsp.so|8181e44d7c1f722218fabd8fe3bf788454a3f586 system_ext/lib64/libwfdcommonutils.so|4350b11e16553d02fded587feaae5cd82cdfaa0a
system_ext/lib64/libwfdsinksm.so|c4d68ecbe0accd24296c18444e5a82b6a24be8d8 system_ext/lib64/libwfdconfigutils.so|08e0be434b9c54035c4ead47ebb7f0322e2a23ba
system_ext/lib64/libwfduibcinterface.so|dca32fe063bdba7ce3b131b16cf112b793ae03ad system_ext/lib64/libwfddisplayconfig.so|59a5cb17ffe46900c0ae26a8937a5ddab80fe283
system_ext/lib64/libwfduibcsink.so|63ea93b1a6aec75a294baf50007270807a819e21 system_ext/lib64/libwfdmminterface.so|b1e33104bc2231c7f75132757a28c918ee4b3889
system_ext/lib64/libwfduibcsinkinterface.so|39c123bd9a4d7a8fa317f8ed4d86972dcfab0423 system_ext/lib64/libwfdmmsink.so|0db18686f52492b89d9feffffd0494371f6a8c18
system_ext/lib64/libwfduibcsrc.so|5557f3bd58c37b7e3b28e13f2f86d55930b14ab6 system_ext/lib64/libwfdmmsrc_system.so|d46d868c7047927c7da7cc3f7274177de655de7d
system_ext/lib64/libwfduibcsrcinterface.so|77cead9bf7b60384fe1e11dc2b25bd99af0b4608 system_ext/lib64/libwfdnative.so|bf8b8596431d578f12f9eead38b5afbb4c54a008
system_ext/priv-app/WfdService/WfdService.apk|7191da7d336f6018ee292af4e69167677b9f5bd1 system_ext/lib64/libwfdrtsp.so|1957934068e8befa237106fbc584457e86ef07da
system_ext/lib64/libwfdservice.so|b0e0b2059142168e856d66cc34448704849f14b4
system_ext/lib64/libwfdsinksm.so|bd2369a1203a3b24115605ec1d27d288b4b62718
system_ext/lib64/libwfduibcinterface.so|d5a578a2159c4681cb9d159b93c1c39b8f3091f7
system_ext/lib64/libwfduibcsink.so|d4cc3afb86003f0e26134f82b503b6deac30b6b5
system_ext/lib64/libwfduibcsinkinterface.so|a875792e5242870cd9a069cb367a6b5031fce2f0
system_ext/lib64/libwfduibcsrc.so|1529ca18c3484b8a3f3d95e9198def564e86fda3
system_ext/lib64/libwfduibcsrcinterface.so|69400030817aa8f6994a525b027bb3dd7cabd0d4
system_ext/lib64/vendor.qti.hardware.sigma_miracast@1.0-halimpl.so|a2d59542267d94c451b85bc0541388d004adb68e
system_ext/lib64/vendor.qti.hardware.sigma_miracast@1.0.so|c2a925b368d2d85a3ed0beebef61fb16209e2303
system_ext/lib64/vendor.qti.hardware.wifidisplaysession@1.0.so|10b4472b777e070e51ed81ab371b05cfc5324d18
system_ext/priv-app/WfdService/WfdService.apk|556c225c72b346319b0c0615e3ed43e1fcf1384d
# WiFi Display - from OnePlus6 - RKQ1.201217.002/2106301530 # WiFi Display - from OnePlus6 - RKQ1.201217.002/2106301530
vendor/bin/wfdhdcphalservice|c459a9dce083f9a2b2d8c7c49903514b87528fda vendor/bin/wfdhdcphalservice|c459a9dce083f9a2b2d8c7c49903514b87528fda
@ -1094,3 +1108,93 @@ vendor/lib64/libmmosal.so|c21735de83eecb9f869ab6268c84f4284428cb35
vendor/lib64/libwfddisplayconfig_proprietary.so|fb6a6c36346a30662d0f79bb8a8656e32cc2e75d vendor/lib64/libwfddisplayconfig_proprietary.so|fb6a6c36346a30662d0f79bb8a8656e32cc2e75d
vendor/lib64/libwfdhdcpcp.so|af856708b2ab67e08f76fd5a746028a448991150 vendor/lib64/libwfdhdcpcp.so|af856708b2ab67e08f76fd5a746028a448991150
vendor/lib64/vendor.qti.hardware.wifidisplaysession@1.0.so|86b6ce7b14bcc8f6ab3215962aab694404c27d14 vendor/lib64/vendor.qti.hardware.wifidisplaysession@1.0.so|86b6ce7b14bcc8f6ab3215962aab694404c27d14
# CarrierSettings - from coral - R-RPP4.200409.0
product/etc/CarrierSettings/airtel_in.pb|ba76d9ecfd74d9e19432adae9b5422ed7f84b747
product/etc/CarrierSettings/att5g_us.pb|bb3047e16ef7e5e10df2e558eccd22b4c7e218a8
product/etc/CarrierSettings/att_us.pb|3783859071b6c2fadb68bb5e7761a994ad24a1df
product/etc/CarrierSettings/bell_ca.pb|08731f06ed601eef96e0f49e10ea102a07611d40
product/etc/CarrierSettings/bluegrass_us.pb|a3867c30fde04dd25672879b10e71093e6a1a27d
product/etc/CarrierSettings/boost_us.pb|7bc04fe92bec403c75fa775287e2f3f388ade735
product/etc/CarrierSettings/bouygues_fr.pb|c6e6485a431ea3bc27970e39bad00f6d1c4829be
product/etc/CarrierSettings/btb_gb.pb|8315914b1325c20f9cc7c146640ade7a17db15f5
product/etc/CarrierSettings/btc_gb.pb|520e35048aa2dc512f91daef0368078762c1b227
product/etc/CarrierSettings/carrier_list.pb|a507ef3823cb112ef8ecf2b4d34a9ec1c2fe0aec
product/etc/CarrierSettings/cellcom_us.pb|e0271b45c00558149207e10aa4432b357d7526d5
product/etc/CarrierSettings/cht_tw.pb|15d5e721135952f5ca61b16a0308ad79f9a50d14
product/etc/CarrierSettings/cricket5g_us.pb|3d08fa78f678a2af8c0e02822ddcea7c3b418978
product/etc/CarrierSettings/cricket_us.pb|3d644f7979bc49b2e02ccd5b874889dad30d74ac
product/etc/CarrierSettings/cspire_us.pb|79d946f83ab94191c83d328215b5e5ba411bc3c6
product/etc/CarrierSettings/default.pb|16a66a14c61179da975b08232d47467822073464
product/etc/CarrierSettings/docomo_jp.pb|208821ce29073a4cbfff539e38fd3052d2217d2a
product/etc/CarrierSettings/ee_gb.pb|3c0559c8a7c45ce5d02817f06e16a37e0094effc
product/etc/CarrierSettings/eplus_de.pb|35270a40cf3e68e038c2325eedf05c1cc9cf7b5f
product/etc/CarrierSettings/fet_tw.pb|0cded656dec55574685cddeecf85602b771a297c
product/etc/CarrierSettings/fido_ca.pb|4155bd3094920d0646a620ccfcf4971976ceb898
product/etc/CarrierSettings/firstnetpacific_us.pb|668a686c4edd7b9da40fb3c034451b23a4f6c3f3
product/etc/CarrierSettings/firstnet_us.pb|1bc9ef44d70063522e86c5aa1be721f3636d3d4e
product/etc/CarrierSettings/fi_us.pb|e2803619ccf36f63bd105cac4e46f6cfa4035b35
product/etc/CarrierSettings/fizz_ca.pb|0d75e2c8b56580c4d4795ee6f1e3b62d2d319b74
product/etc/CarrierSettings/freedommobile_ca.pb|e8276ab551a1aac1df8ad965d76e67225a3b34e7
product/etc/CarrierSettings/h3_at.pb|89111b9fe76e234235ede8fa6eda67c43b1ba190
product/etc/CarrierSettings/h3_gb.pb|2811b99744f9833edca741ad76ad66485e7c844a
product/etc/CarrierSettings/idea_in.pb|77ad6d787c3717f3d0ffc36715338341949bdd22
product/etc/CarrierSettings/idmobile_gb.pb|ab55b578bf804e817c65f0277132bfb300db89c1
product/etc/CarrierSettings/kddi_jp.pb|1e74d06b4c68a19dc928294d851c556a279829dd
product/etc/CarrierSettings/kddimvno_jp.pb|771af311f37b54488d08eaa98de94cc205a09000
product/etc/CarrierSettings/koodo_ca.pb|343da5aec9403308007d042cb1f19e216f87c9b3
product/etc/CarrierSettings/luckymobile_ca.pb|1247e849aae3111c7d92187077cfc505c8b65422
product/etc/CarrierSettings/o2_de.pb|f3eb29fff315678e9b6d5bbbc7428aecdc3153f0
product/etc/CarrierSettings/o2postpaid_gb.pb|cedebdb968dd2303e347bc0569e4d34d6ab1b0a8
product/etc/CarrierSettings/o2prepaid_de.pb|0861eafd2589ca8e50e6d21c109239ba5fd167e1
product/etc/CarrierSettings/o2prepaid_gb.pb|bf6ec3e1b82f23550fb9ea7d7def823c9088fadf
product/etc/CarrierSettings/optus_au.pb|3cfe56f32eac5df6976a692cfbfb35530e43917a
product/etc/CarrierSettings/orange_es.pb|25c474061c6437f713720116c8122d30027845ef
product/etc/CarrierSettings/orange_fr.pb|dd3b9bf9151ec965e845e1ea96bd9752816e16f3
product/etc/CarrierSettings/others.pb|d2cf5a92634fac82dc4a60e1ada137033db4a130
product/etc/CarrierSettings/pcmobilebell_ca.pb|285714983398a4c886f189e380d22babd6968e3b
product/etc/CarrierSettings/rakuten_jp.pb|b1204b307bb123183df6611dcf6c5f61a6c5e4df
product/etc/CarrierSettings/rjio_in.pb|3ca38e1f8cf522b2b6291ae08649cbfa63ab8b0c
product/etc/CarrierSettings/rogers_ca.pb|a9201c7646f6f93aecba7fe854e7ee25917d6605
product/etc/CarrierSettings/sfr_fr.pb|ab1e380d2400e1299dd03e97dc7dbe97776ae400
product/etc/CarrierSettings/singtel_sg.pb|4ad088f046381921b451e2eddc04355ea4c9b1ce
product/etc/CarrierSettings/softbank_jp.pb|c1a200dff0b51a9532b7f00b24ee3f6b9b3ef6b8
product/etc/CarrierSettings/solomobile_ca.pb|83288e185294c7d0900364c18714ba6ed2cae657
product/etc/CarrierSettings/spectrum_us.pb|2e80bb018fa7248712ff1580236bc32501764f31
product/etc/CarrierSettings/sprintprepaid_us.pb|f8bf30e91aedcf3170d3830ebb7e47bde117a899
product/etc/CarrierSettings/sprint_us.pb|0c3ee0fa9a8c70b2ec5527bf54948ca899046a28
product/etc/CarrierSettings/sprintwholesale_us.pb|3e85bc601be19e9e46cbf00b26fdce4b05cb2973
product/etc/CarrierSettings/starhub_sg.pb|49c526eae01a3b15528e0bb405262045997138dd
product/etc/CarrierSettings/swisscom_ch.pb|862e3cee34a9d8758319efa3f858869dc2c6bb8e
product/etc/CarrierSettings/swisscom_li.pb|b425f07c8c812e1d64c752e6bc7b2c9e96b9666a
product/etc/CarrierSettings/tdc_dk.pb|a543c4db47674d4b47c4636e01774746d95e347e
product/etc/CarrierSettings/tele2_se.pb|2ad5436b590570b0620962f7460bef2d0d841c75
product/etc/CarrierSettings/telekom_de.pb|08d1e88adc534bf1bb991eea143b95e1b8cdcd17
product/etc/CarrierSettings/telenor_dk.pb|061a867c381b0579546933de589d4eb01e81561d
product/etc/CarrierSettings/telenor_no.pb|edff85791c6dd1001420db3ae204c3bb55b4511f
product/etc/CarrierSettings/telia_no.pb|d06154f660f724e5863bf6509a194734f12d6570
product/etc/CarrierSettings/telia_se.pb|a45ce80e79b7c9dc6151c650fa12d815f74a5650
product/etc/CarrierSettings/telstra_au.pb|837a0575facc19babf8563a447897fe1f286d9fc
product/etc/CarrierSettings/telus_ca.pb|269aa3b0325eb97717ff5587e335e90ef08b09bc
product/etc/CarrierSettings/tim_it.pb|3e04089cf886f9a75b79f9a78fb441fa8cafb463
product/etc/CarrierSettings/tmobile_nl.pb|936f75e2958a4e09b8bd3d278bb562e94b0ccf1d
product/etc/CarrierSettings/tmobile_us.pb|08f99051fd8ba5f9d65d80cf2c66d51d8114282a
product/etc/CarrierSettings/tracfonetmo_us.pb|b610ce42a979fd34fb1b36fc725a2b35a818accb
product/etc/CarrierSettings/tracfoneverizon_us.pb|88dc4c0a3e9363398bf72537e99268f84b193c5d
product/etc/CarrierSettings/twm_tw.pb|e88c01147316149150261f51dc31589caa42c429
product/etc/CarrierSettings/uscc_us.pb|18521df72bc65b97bb2e013d4e4668456fd1f48e
product/etc/CarrierSettings/verizon_us.pb|d7cb3e2a171acc3db56631761d6afa83e55fd288
product/etc/CarrierSettings/virgin_us.pb|47fa194634daead004750ee2e9a4d95f6f578ecd
product/etc/CarrierSettings/videotron_ca.pb|1e52d7ae3357ff651e35f1ddee430f8ef07366d9
product/etc/CarrierSettings/virgin_ca.pb|7ad8d1fd3dce4eaf5955a8911dad5ce294ae1dda
product/etc/CarrierSettings/visible_us.pb|a496dcbfe16ab08286d87ba45a988272d51d9241
product/etc/CarrierSettings/vodafone_au.pb|a6153c795001011663fe978128ccb846afb2dadc
product/etc/CarrierSettings/vodafone_de.pb|595913b107e573077dcac3244fd9cead48993520
product/etc/CarrierSettings/vodafone_es.pb|7aeb052cc04916ddc0ea735d80eee1a12565495e
product/etc/CarrierSettings/vodafone_gb.pb|97bd59b0ca302e77cd3bfc169ee9dcd1de2c001c
product/etc/CarrierSettings/vodafone_in.pb|0b47c74af033e7423e175c3eb834768f487ffef0
product/etc/CarrierSettings/vodafone_it.pb|d4c0a66bda9d4d605a413a57227e7247e322193b
product/etc/CarrierSettings/vodafone_nl.pb|ddb242406bfa4ec623110c0b448329f2fa2c879f
product/etc/CarrierSettings/vodafone_tr.pb|2669f7cb9f3098d265a9c25319c64d1dc630c1ce
product/etc/CarrierSettings/xfinity_us.pb|3368bac024d407ee16f4c7b16252c6f9b97dfa24
-product/priv-app/CarrierSettings/CarrierSettings.apk|e4ce66de07d6123e14bcef26b3c8e6ecc143934c

View file

@ -18,13 +18,45 @@ import common
import re import re
def FullOTA_InstallEnd(info): def FullOTA_InstallEnd(info):
OTA_UpdateFirmware(info)
OTA_InstallEnd(info) OTA_InstallEnd(info)
return return
def IncrementalOTA_InstallEnd(info): def IncrementalOTA_InstallEnd(info):
OTA_UpdateFirmware(info)
OTA_InstallEnd(info) OTA_InstallEnd(info)
return return
def OTA_UpdateFirmware(info):
info.script.AppendExtra('ui_print("Patching firmware images unconditionally...");')
info.script.AppendExtra('package_extract_file("install/firmware-update/cmnlib64.mbn", "/dev/block/bootdevice/by-name/cmnlib64");')
info.script.AppendExtra('package_extract_file("install/firmware-update/cmnlib.mbn", "/dev/block/bootdevice/by-name/cmnlib");')
info.script.AppendExtra('package_extract_file("install/firmware-update/hyp.mbn", "/dev/block/bootdevice/by-name/hyp");')
info.script.AppendExtra('package_extract_file("install/firmware-update/BTFM.bin", "/dev/block/bootdevice/by-name/bluetooth");')
info.script.AppendExtra('package_extract_file("install/firmware-update/tz.mbn", "/dev/block/bootdevice/by-name/tz");')
info.script.AppendExtra('package_extract_file("install/firmware-update/aop.mbn", "/dev/block/bootdevice/by-name/aop");')
info.script.AppendExtra('package_extract_file("install/firmware-update/xbl_config.elf", "/dev/block/bootdevice/by-name/xbl_config");')
info.script.AppendExtra('package_extract_file("install/firmware-update/keymaster64.mbn", "/dev/block/bootdevice/by-name/keymaster");')
info.script.AppendExtra('package_extract_file("install/firmware-update/qupv3fw.elf", "/dev/block/bootdevice/by-name/qupfw");')
info.script.AppendExtra('package_extract_file("install/firmware-update/abl.elf", "/dev/block/bootdevice/by-name/abl");')
info.script.AppendExtra('package_extract_file("install/firmware-update/dspso.bin", "/dev/block/bootdevice/by-name/dsp");')
info.script.AppendExtra('package_extract_file("install/firmware-update/devcfg.mbn", "/dev/block/bootdevice/by-name/devcfg");')
info.script.AppendExtra('package_extract_file("install/firmware-update/storsec.mbn", "/dev/block/bootdevice/by-name/storsec");')
info.script.AppendExtra('package_extract_file("install/firmware-update/xbl.elf", "/dev/block/bootdevice/by-name/xbl");')
info.script.AppendExtra('package_extract_file("install/firmware-update/cmnlib64.mbn", "/dev/block/bootdevice/by-name/cmnlib64bak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/cmnlib.mbn", "/dev/block/bootdevice/by-name/cmnlibbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/hyp.mbn", "/dev/block/bootdevice/by-name/hypbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/tz.mbn", "/dev/block/bootdevice/by-name/tzbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/aop.mbn", "/dev/block/bootdevice/by-name/aopbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/xbl_config.elf", "/dev/block/bootdevice/by-name/xbl_configbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/keymaster64.mbn", "/dev/block/bootdevice/by-name/keymasterbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/qupv3fw.elf", "/dev/block/bootdevice/by-name/qupfwbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/abl.elf", "/dev/block/bootdevice/by-name/ablbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/devcfg.mbn", "/dev/block/bootdevice/by-name/devcfgbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/storsec.mbn", "/dev/block/bootdevice/by-name/storsecbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/xbl.elf", "/dev/block/bootdevice/by-name/xblbak");')
info.script.AppendExtra('package_extract_file("install/firmware-update/NON-HLOS.bin", "/dev/block/bootdevice/by-name/modem");')
def AddImage(info, dir, basename, dest): def AddImage(info, dir, basename, dest):
name = basename name = basename
data = info.input_zip.read(dir + "/" + basename) data = info.input_zip.read(dir + "/" + basename)

View file

@ -13,11 +13,11 @@ vendor /vendor
odm /odm ext4 ro,barrier=1,discard wait,logical,first_stage_mount odm /odm ext4 ro,barrier=1,discard wait,logical,first_stage_mount
/dev/block/bootdevice/by-name/recovery /recovery emmc defaults defaults /dev/block/bootdevice/by-name/recovery /recovery emmc defaults defaults
/dev/block/bootdevice/by-name/boot /boot emmc defaults defaults /dev/block/bootdevice/by-name/boot /boot emmc defaults defaults
/dev/block/by-name/logdump /metadata ext4 nosuid,nodev,noatime,discard,data=journal,commit=1 wait,check,formattable,first_stage_mount /dev/block/by-name/logdump /metadata ext4 nosuid,nodev,noatime,discard wait,check,formattable,first_stage_mount
/dev/block/bootdevice/by-name/userdata /data ext4 noatime,nosuid,noatime,nodev,barrier=1,noauto_da_alloc,discard,lazytime latemount,wait,check,fileencryption=ice,reservedsize=128M /dev/block/bootdevice/by-name/userdata /data ext4 noatime,nosuid,noatime,nodev,barrier=1,noauto_da_alloc,discard,lazytime latemount,wait,check,fileencryption=ice,reservedsize=128M
/dev/block/bootdevice/by-name/cache /cache ext4 nosuid,noatime,nodev,barrier=1 wait /dev/block/bootdevice/by-name/cache /cache ext4 nosuid,noatime,nodev,barrier=1 wait
/devices/platform/soc/8804000.sdhci/mmc_host* /storage/sdcard1 vfat nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=userdata /devices/platform/soc/8804000.sdhci/mmc_host* /storage/sdcard1 vfat nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=footer
/devices/platform/soc/1da4000.ufshc_card/host* /storage/sdcard1 vfat nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=userdata /devices/platform/soc/1da4000.ufshc_card/host* /storage/sdcard1 vfat nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=footer
/dev/block/bootdevice/by-name/modem /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait /dev/block/bootdevice/by-name/modem /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait
/dev/block/bootdevice/by-name/dsp /vendor/dsp ext4 ro,nosuid,nodev,barrier=1 wait /dev/block/bootdevice/by-name/dsp /vendor/dsp ext4 ro,nosuid,nodev,barrier=1 wait
/dev/block/bootdevice/by-name/persist /mnt/vendor/persist ext4 nosuid,noatime,nodev,barrier=1 wait /dev/block/bootdevice/by-name/persist /mnt/vendor/persist ext4 nosuid,noatime,nodev,barrier=1 wait

View file

@ -1379,3 +1379,15 @@ on property:sys.usb.config=midi && property:sys.usb.configfs=1
on property:sys.usb.config=midi,adb && property:sys.usb.configfs=1 on property:sys.usb.config=midi,adb && property:sys.usb.configfs=1
write /config/usb_gadget/g1/idVendor 0x18d1 write /config/usb_gadget/g1/idVendor 0x18d1
write /config/usb_gadget/g1/idProduct 0x4ee9 write /config/usb_gadget/g1/idProduct 0x4ee9
on property:vendor.usb.eud=1
write /config/usb_gadget/g1/configs/b.1/MaxPower 1
write /sys/module/eud/parameters/enable 1
write /sys/kernel/debug/pmic-votable/USB_ICL/force_active 1
write /sys/kernel/debug/pmic-votable/USB_ICL/force_val 500
on property:vendor.usb.eud=0
write /sys/kernel/debug/pmic-votable/USB_ICL/force_active 0
write /sys/kernel/debug/pmic-votable/USB_ICL/force_val 0
write /config/usb_gadget/g1/configs/b.1/MaxPower 0
write /sys/module/eud/parameters/enable 0

View file

@ -101,6 +101,7 @@ if [ $feature_id == 6 ]; then
echo 940800000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/min_freq echo 940800000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/min_freq
echo 1017600000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/max_freq echo 1017600000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/max_freq
echo 3 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel echo 3 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
echo {class:ddr, res:fixed, val: 1016} > /sys/kernel/debug/aop_send_message
setprop vendor.sku_identified 1 setprop vendor.sku_identified 1
elif [ $feature_id == 5 ]; then elif [ $feature_id == 5 ]; then
echo "SKU Configured : SA6150" echo "SKU Configured : SA6150"
@ -125,6 +126,7 @@ elif [ $feature_id == 5 ]; then
echo 940800000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/min_freq echo 940800000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/min_freq
echo 1363200000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/max_freq echo 1363200000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/max_freq
echo 2 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel echo 2 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
echo {class:ddr, res:fixed, val: 1333} > /sys/kernel/debug/aop_send_message
setprop vendor.sku_identified 1 setprop vendor.sku_identified 1
elif [ $feature_id == 4 || $feature_id == 3 ]; then elif [ $feature_id == 4 || $feature_id == 3 ]; then
echo "SKU Configured : SA6155" echo "SKU Configured : SA6155"
@ -149,6 +151,7 @@ elif [ $feature_id == 4 || $feature_id == 3 ]; then
echo 940800000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/min_freq echo 940800000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/min_freq
echo 1363200000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/max_freq echo 1363200000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/max_freq
echo 0 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel echo 0 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
echo {class:ddr, res:fixed, val: 1555} > /sys/kernel/debug/aop_send_message
setprop vendor.sku_identified 1 setprop vendor.sku_identified 1
else else
echo "unknown feature_id value" $feature_id echo "unknown feature_id value" $feature_id
@ -173,6 +176,7 @@ else
echo 940800000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/min_freq echo 940800000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/min_freq
echo 1363200000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/max_freq echo 1363200000 > /sys/class/devfreq/soc\:qcom,cpu6-cpu-l3-lat/max_freq
echo 0 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel echo 0 > /sys/class/kgsl/kgsl-3d0/max_pwrlevel
echo {class:ddr, res:fixed, val: 1555} > /sys/kernel/debug/aop_send_message
setprop vendor.sku_identified 1 setprop vendor.sku_identified 1
fi fi
} }
@ -341,7 +345,9 @@ function configure_zram_parameters() {
# For >4GB Non-Go device, size = 4GB # For >4GB Non-Go device, size = 4GB
# And enable lz4 zram compression for Go targets. # And enable lz4 zram compression for Go targets.
if [ "$low_ram" == "true" ]; then
echo lz4 > /sys/block/zram0/comp_algorithm echo lz4 > /sys/block/zram0/comp_algorithm
fi
if [ -f /sys/block/zram0/disksize ]; then if [ -f /sys/block/zram0/disksize ]; then
if [ -f /sys/block/zram0/use_dedup ]; then if [ -f /sys/block/zram0/use_dedup ]; then
@ -5041,6 +5047,12 @@ case "$target" in
;; ;;
esac esac
case "$target" in
"qsd8650a_st1x")
mount -t debugfs none /sys/kernel/debug
;;
esac
chown -h system /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate chown -h system /sys/devices/system/cpu/cpufreq/ondemand/sampling_rate
chown -h system /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor chown -h system /sys/devices/system/cpu/cpufreq/ondemand/sampling_down_factor
chown -h system /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy chown -h system /sys/devices/system/cpu/cpufreq/ondemand/io_is_busy
@ -5127,6 +5139,20 @@ case "$target" in
;; ;;
esac esac
# Install AdrenoTest.apk if not already installed
if [ -f /data/prebuilt/AdrenoTest.apk ]; then
if [ ! -d /data/data/com.qualcomm.adrenotest ]; then
pm install /data/prebuilt/AdrenoTest.apk
fi
fi
# Install SWE_Browser.apk if not already installed
if [ -f /data/prebuilt/SWE_AndroidBrowser.apk ]; then
if [ ! -d /data/data/com.android.swe.browser ]; then
pm install /data/prebuilt/SWE_AndroidBrowser.apk
fi
fi
# Change adj level and min_free_kbytes setting for lowmemory killer to kick in # Change adj level and min_free_kbytes setting for lowmemory killer to kick in
case "$target" in case "$target" in
"msm8660") "msm8660")

View file

@ -35,12 +35,26 @@ on early-init
rm /data/resource-cache rm /data/resource-cache
rm /data/system/package_cache rm /data/system/package_cache
mount debugfs debugfs /sys/kernel/debug
chmod 0755 /sys/kernel/debug
# Change ownership of hw_recovery related nodes
chown system graphics /sys/kernel/debug/dri/0/debug/dump
chown system graphics /sys/kernel/debug/dri/0/debug/recovery_reg
chown system graphics /sys/kernel/debug/dri/0/debug/recovery_dbgbus
chown system graphics /sys/kernel/debug/dri/0/debug/recovery_vbif_dbgbus
# Change ownership of sw_sync node
chown system graphics /sys/kernel/debug/sync/sw_sync
chmod 0666 /sys/kernel/debug/sync/sw_sync
chown root system /dev/kmsg chown root system /dev/kmsg
chmod 0620 /dev/kmsg chmod 0620 /dev/kmsg
# Load WIGIG platform driver # Load WIGIG platform driver
exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d /vendor/lib/modules msm_11ad_proxy exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d /vendor/lib/modules msm_11ad_proxy
on init on init
# Support legacy paths # Support legacy paths
symlink /sdcard /mnt/sdcard symlink /sdcard /mnt/sdcard
symlink /sdcard /storage/sdcard0 symlink /sdcard /storage/sdcard0
@ -65,11 +79,9 @@ on init
write /sys/block/mmcblk0/queue/nr_requests 256 write /sys/block/mmcblk0/queue/nr_requests 256
write /sys/block/mmcblk0/queue/iostats 0 write /sys/block/mmcblk0/queue/iostats 0
# report max frequency to unity tasks.
write /proc/sys/kernel/sched_lib_name "com.miHoYo.,UnityMain,libunity.so"
write /proc/sys/kernel/sched_lib_mask_force 255
on post-fs on post-fs
chmod 0755 /sys/kernel/debug/tracing
# Start services for bootanim # Start services for bootanim
start surfaceflinger start surfaceflinger
start bootanim start bootanim
@ -140,6 +152,8 @@ on boot
chown bluetooth bluetooth /sys/module/hci_smd/parameters/hcismd_set chown bluetooth bluetooth /sys/module/hci_smd/parameters/hcismd_set
chown system system /sys/module/msm_core/parameters/polling_interval chown system system /sys/module/msm_core/parameters/polling_interval
chown system system /sys/module/msm_core/parameters/disabled chown system system /sys/module/msm_core/parameters/disabled
chown system system /sys/kernel/debug/msm_core/enable
chown system system /sys/kernel/debug/msm_core/ptable
chown system system /sys/kernel/boot_slpi/ssr chown system system /sys/kernel/boot_slpi/ssr
chown system system /sys/module/radio_iris_transport/parameters/fmsmd_set chown system system /sys/module/radio_iris_transport/parameters/fmsmd_set
chmod 0660 /sys/module/bluetooth_power/parameters/power chmod 0660 /sys/module/bluetooth_power/parameters/power
@ -200,6 +214,9 @@ on boot
setprop ro.telephony.call_ring.multiple false setprop ro.telephony.call_ring.multiple false
#enable camera read sensors data
setprop persist.camera.gyro.disable 0
#Remove SUID bit for iproute2 ip tool #Remove SUID bit for iproute2 ip tool
chmod 0755 /system/bin/ip chmod 0755 /system/bin/ip
@ -1042,6 +1059,16 @@ service vendor.audio-hal /vendor/bin/hw/android.hardware.audio.service
socket audio_hw_socket seqpacket 0666 system system socket audio_hw_socket seqpacket 0666 system system
onrestart restart audioserver onrestart restart audioserver
service vendor.thermal-hal-2-0 /vendor/bin/hw/android.hardware.thermal@2.0-service.pixel
override
interface android.hardware.thermal@1.0::IThermal default
interface android.hardware.thermal@2.0::IThermal default
class hal
user system
group system
priority -20
disabled
on property:sys.boot_completed=1 on property:sys.boot_completed=1
# Restrict permissions to socket file # Restrict permissions to socket file
# to hide Magisk & co. # to hide Magisk & co.

View file

@ -1,50 +0,0 @@
# Copyright (c) 2009-2012, 2014-2015, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of The Linux Foundation nor
# the names of its contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
#import /init.recovery.qcom_decrypt.rc
on fs
wait /dev/block/platform/soc/${ro.boot.bootdevice}
symlink /dev/block/platform/soc/${ro.boot.bootdevice} /dev/block/bootdevice
export ANDROID_ROOT /system_root
on early-init
# Enable double-tap to wake
write /sys/devices/virtual/touch/tp_dev/gesture_on 1
on init
# Workaround for setting AVB version
setprop sys.usb.configfs 1
setprop ro.boot.avb_version 1.0
setprop ro.boot.vbmeta.avb_version ${ro.boot.avb_version}
setprop vendor.gatekeeper.disable_spu true
#on boot
# setprop sys.usb.config adb
# start health-hal-2-1
# chown system system /sys/class/touch/tp_dev/gesture_on
# chown 0660 /sys/class/touch/tp_dev/gesture_on

View file

@ -1,124 +0,0 @@
# Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# * Neither the name of The Linux Foundation nor
# the names of its contributors may be used to endorse or promote
# products derived from this software without specific prior written
# permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
on boot
write /sys/class/android_usb/android0/iSerial ${ro.serialno}
mount configfs none /config
mkdir /config/usb_gadget/g1 0770
mkdir /config/usb_gadget/g2 0770
mkdir /config/usb_gadget/g1/strings/0x409 0770
mkdir /config/usb_gadget/g2/strings/0x409 0770
write /config/usb_gadget/g1/bcdUSB 0x0200
write /config/usb_gadget/g2/bcdUSB 0x0200
write /config/usb_gadget/g1/os_desc/use 1
write /config/usb_gadget/g1/strings/0x409/serialnumber ${ro.serialno}
write /config/usb_gadget/g2/strings/0x409/serialnumber ${ro.serialno}
write /config/usb_gadget/g1/strings/0x409/manufacturer ${ro.product.manufacturer}
write /config/usb_gadget/g2/strings/0x409/manufacturer ${ro.product.manufacturer}
write /config/usb_gadget/g1/strings/0x409/product ${ro.product.model}
write /config/usb_gadget/g2/strings/0x409/product ${ro.product.model}
mkdir /config/usb_gadget/g1/functions/mass_storage.0
mkdir /config/usb_gadget/g1/functions/mtp.gs0
mkdir /config/usb_gadget/g1/functions/ptp.gs1
mkdir /config/usb_gadget/g1/functions/accessory.gs2
mkdir /config/usb_gadget/g1/functions/audio_source.gs3
mkdir /config/usb_gadget/g1/functions/midi.gs5
mkdir /config/usb_gadget/g1/functions/ffs.adb
mkdir /config/usb_gadget/g1/functions/diag.diag
mkdir /config/usb_gadget/g1/functions/diag.diag_mdm
mkdir /config/usb_gadget/g1/functions/cser.dun.0
mkdir /config/usb_gadget/g1/functions/cser.nmea.1
mkdir /config/usb_gadget/g1/functions/cser.dun.2
mkdir /config/usb_gadget/g1/functions/gsi.rmnet
mkdir /config/usb_gadget/g1/functions/gsi.rndis
mkdir /config/usb_gadget/g1/functions/gsi.dpl
mkdir /config/usb_gadget/g1/functions/qdss.qdss
mkdir /config/usb_gadget/g1/functions/qdss.qdss_mdm
mkdir /config/usb_gadget/g1/functions/rndis_bam.rndis
mkdir /config/usb_gadget/g1/functions/rndis.rndis
mkdir /config/usb_gadget/g1/functions/rmnet_bam.rmnet
mkdir /config/usb_gadget/g1/functions/rmnet_bam.dpl
mkdir /config/usb_gadget/g1/functions/rmnet_bam.rmnet_bam_dmux
mkdir /config/usb_gadget/g1/functions/rmnet_bam.dpl_bam_dmux
mkdir /config/usb_gadget/g1/functions/ncm.0
mkdir /config/usb_gadget/g1/functions/ccid.ccid
mkdir /config/usb_gadget/g1/functions/uac2.0
mkdir /config/usb_gadget/g1/functions/uvc.0
mkdir /config/usb_gadget/g1/configs/b.1 0770
mkdir /config/usb_gadget/g2/configs/b.1 0770
mkdir /config/usb_gadget/g1/configs/b.1/strings/0x409 0770
mkdir /config/usb_gadget/g2/configs/b.1/strings/0x409 0770
write /config/usb_gadget/g1/os_desc/b_vendor_code 0x1
write /config/usb_gadget/g1/os_desc/qw_sign "MSFT100"
symlink /config/usb_gadget/g1/configs/b.1 /config/usb_gadget/g1/os_desc/b.1
mkdir /dev/usb-ffs 0775 shell system
mkdir /dev/usb-ffs/adb 0770 shell system
mount functionfs adb /dev/usb-ffs/adb uid=2000,gid=1000,rmode=0770,fmode=0660
write /sys/class/android_usb/android0/f_ffs/aliases adb
setprop vendor.usb.controller ${sys.usb.controller}
on property:sys.usb.config=none
write /config/usb_gadget/g1/UDC "none"
stop adbd
setprop sys.usb.ffs.ready 0
write /config/usb_gadget/g1/bDeviceClass 0
write /config/usb_gadget/g1/bDeviceSubClass 0
write /config/usb_gadget/g1/bDeviceProtocol 0
setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=mtp,adb
start adbd
on property:sys.usb.ffs.ready=1 && property:sys.usb.config=mtp,adb
write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "mtp_adb"
rm /config/usb_gadget/g1/configs/b.1/f1
rm /config/usb_gadget/g1/configs/b.1/f2
rm /config/usb_gadget/g1/configs/b.1/f3
rm /config/usb_gadget/g1/configs/b.1/f4
rm /config/usb_gadget/g1/configs/b.1/f5
write /config/usb_gadget/g1/idVendor 0x05C6
write /config/usb_gadget/g1/idProduct 0x9039
symlink /config/usb_gadget/g1/functions/mtp.gs0 /config/usb_gadget/g1/configs/b.1/f1
symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f2
write /config/usb_gadget/g1/UDC ${sys.usb.controller}
setprop sys.usb.state ${sys.usb.config}
on property:sys.usb.config=sideload
start adbd
on property:sys.usb.ffs.ready=1 && property:sys.usb.config=sideload
write /config/usb_gadget/g1/configs/b.1/strings/0x409/configuration "adb"
rm /config/usb_gadget/g1/configs/b.1/f1
rm /config/usb_gadget/g1/configs/b.1/f2
rm /config/usb_gadget/g1/configs/b.1/f3
rm /config/usb_gadget/g1/configs/b.1/f4
rm /config/usb_gadget/g1/configs/b.1/f5
write /config/usb_gadget/g1/idVendor 0x18d1
write /config/usb_gadget/g1/idProduct 0x4ee7
symlink /config/usb_gadget/g1/functions/ffs.adb /config/usb_gadget/g1/configs/b.1/f1
write /config/usb_gadget/g1/UDC ${sys.usb.controller}
setprop sys.usb.state ${sys.usb.config}

104
sdm710.mk
View file

@ -3,10 +3,8 @@ $(call inherit-product, $(SRC_TARGET_DIR)/product/product_launched_with_p.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/full_base_telephony.mk) $(call inherit-product, $(SRC_TARGET_DIR)/product/full_base_telephony.mk)
OVERRIDE_PRODUCT_COMPRESSED_APEX := false
# Get non-open-source specific aspects # Get non-open-source specific aspects
$(call inherit-product, vendor/lenovo/sdm710-common/sdm710-common-vendor.mk) $(call inherit-product-if-exists, vendor/lenovo/sdm710-common/sdm710-common-vendor.mk)
# Setup dalvik vm configs # Setup dalvik vm configs
$(call inherit-product, frameworks/native/build/phone-xhdpi-4096-dalvik-heap.mk) $(call inherit-product, frameworks/native/build/phone-xhdpi-4096-dalvik-heap.mk)
@ -62,23 +60,6 @@ PRODUCT_COPY_FILES += \
frameworks/native/data/etc/android.software.midi.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.midi.xml \ frameworks/native/data/etc/android.software.midi.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.midi.xml \
frameworks/native/data/etc/android.software.sip.voip.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.sip.voip.xml frameworks/native/data/etc/android.software.sip.voip.xml:$(TARGET_COPY_OUT_VENDOR)/etc/permissions/android.software.sip.voip.xml
# QPR3
PRODUCT_PACKAGES += \
libaudioroute \
libaudioroute.vendor \
libstagefrighthw \
libstagefright_softomx_plugin.vendor \
libprocessgroup.vendor \
libsqlite.vendor \
liblz4.vendor \
libssl.vendor \
libcurl.vendor \
libjsoncpp.vendor \
libsqlite.vendor \
libtinyxml \
libavservices_minijail.vendor \
libpng.vendor
# AID/fs configs # AID/fs configs
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
fs_config_files fs_config_files
@ -160,11 +141,6 @@ PRODUCT_PACKAGES += \
init.target.rc \ init.target.rc \
ueventd.qcom.rc ueventd.qcom.rc
# Recovery init
PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/rootdir/etc/init.recovery.qcom.rc:$(TARGET_RECOVERY_OUT)/root/init.recovery.qcom.rc \
$(LOCAL_PATH)/rootdir/etc/init.recovery.usb.rc:$(TARGET_RECOVERY_OUT)/root/init.recovery.usb.rc
# Codec2 # Codec2
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
libcodec2_vndk.vendor \ libcodec2_vndk.vendor \
@ -204,8 +180,7 @@ PRODUCT_PACKAGES += \
vendor.display.config@2.0 \ vendor.display.config@2.0 \
vendor.display.config@2.0.vendor \ vendor.display.config@2.0.vendor \
memtrack.sdm710 \ memtrack.sdm710 \
vendor.qti.hardware.display.allocator@1.0-service \ vendor.qti.hardware.display.allocator@1.0-service
vendor.qti.hardware.display.config-V5-ndk
PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \ PRODUCT_DEFAULT_PROPERTY_OVERRIDES += \
ro.surface_flinger.has_HDR_display=true \ ro.surface_flinger.has_HDR_display=true \
@ -219,14 +194,6 @@ PRODUCT_PACKAGES += \
android.hardware.drm@1.3.vendor \ android.hardware.drm@1.3.vendor \
android.hardware.drm-service.clearkey android.hardware.drm-service.clearkey
# CBS_init
PRODUCT_PACKAGES += \
libcrypto-v33
# Fastbootd
PRODUCT_PACKAGES += \
fastbootd
# Gatekeeper # Gatekeeper
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.gatekeeper@1.0 \ android.hardware.gatekeeper@1.0 \
@ -258,13 +225,12 @@ PRODUCT_PACKAGES += \
# Fingerprint # Fingerprint
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.biometrics.fingerprint-service.xiaomi \ android.hardware.biometrics.fingerprint@2.1.vendor
android.hardware.biometrics.fingerprint@2.1.vendor \
# Dynamic Partitions # Dynamic Partitions
PRODUCT_BUILD_SUPER_PARTITION := false PRODUCT_BUILD_SUPER_PARTITION := false
PRODUCT_USE_DYNAMIC_PARTITIONS := true PRODUCT_USE_DYNAMIC_PARTITIONS := true
PRODUCT_RETROFIT_DYNAMIC_PARTITIONS := true
PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/configs/flash_super_dummy.sh:install/bin/flash_super_dummy.sh $(LOCAL_PATH)/configs/flash_super_dummy.sh:install/bin/flash_super_dummy.sh
@ -283,9 +249,6 @@ PRODUCT_PACKAGES += \
# HWUI # HWUI
HWUI_COMPILE_FOR_PERF := true HWUI_COMPILE_FOR_PERF := true
# Kernel
PRODUCT_SET_DEBUGFS_RESTRICTIONS := true
# Input # Input
PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/keylayout/fts_ts.kl:$(TARGET_COPY_OUT_SYSTEM)/usr/keylayout/fts_ts.kl $(LOCAL_PATH)/keylayout/fts_ts.kl:$(TARGET_COPY_OUT_SYSTEM)/usr/keylayout/fts_ts.kl
@ -310,18 +273,14 @@ PRODUCT_PACKAGES += \
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.light@2.0-service.lenovo_sdm710 android.hardware.light@2.0-service.lenovo_sdm710
# Lineage Health # Livedisplay
PRODUCT_PACKAGES += \ ifeq ($(findstring Plus, $(CUSTOM_VERSION)),)
vendor.lineage.health-service.default
# LiveDisplay
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
vendor.lineage.livedisplay@2.0-service-sdm vendor.lineage.livedisplay@2.0-service-sdm
endif
# Media # Media
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
#android.hardware.media.omx@1.0-impl \
android.hardware.media.omx@1.0-service \
libavservices_minijail \ libavservices_minijail \
libavservices_minijail.vendor \ libavservices_minijail.vendor \
libc2dcolorconvert \ libc2dcolorconvert \
@ -333,8 +292,7 @@ PRODUCT_PACKAGES += \
libOmxQcelp13Enc \ libOmxQcelp13Enc \
libOmxVdec \ libOmxVdec \
libOmxVenc \ libOmxVenc \
libstagefrighthw \ libstagefrighthw
libstagefright_omx.vendor
PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/configs/media_codecs.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs.xml \ $(LOCAL_PATH)/configs/media_codecs.xml:$(TARGET_COPY_OUT_VENDOR)/etc/media_codecs.xml \
@ -388,12 +346,16 @@ PRODUCT_PACKAGES += \
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
libqti-perfd-client libqti-perfd-client
# PocketMode
PRODUCT_PACKAGES += \
LenovoPocketMode
# Power # Power
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.power@1.2 \ android.hardware.power@1.2 \
android.hardware.power@1.2.vendor \ android.hardware.power@1.2.vendor \
android.hardware.power.stats@1.0-service.mock \ android.hardware.power.stats@1.0-service.mock \
android.hardware.power-service.xiaomi-libperfmgr android.hardware.power-service.lenovo-sdm710-libperfmgr
PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/configs/powerhint.json:$(TARGET_COPY_OUT_VENDOR)/etc/powerhint.json $(LOCAL_PATH)/configs/powerhint.json:$(TARGET_COPY_OUT_VENDOR)/etc/powerhint.json
@ -407,16 +369,7 @@ PRODUCT_DEXPREOPT_SPEED_APPS += \
# Protobuf # Protobuf
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
libprotobuf-cpp-full-vendorcompat \ libprotobuf-cpp-full-vendorcompat \
libprotobuf-cpp-full-3.9.1-vendorcompat \ libprotobuf-cpp-lite-vendorcompat
libprotobuf-cpp-lite-3.9.1-vendorcompat
PRODUCT_COPY_FILES += \
prebuilts/vndk/v29/arm/arch-arm-armv7-a-neon/shared/vndk-core/libprotobuf-cpp-full.so:$(TARGET_COPY_OUT_VENDOR)/lib/libprotobuf-cpp-full.so \
prebuilts/vndk/v29/arm64/arch-arm64-armv8-a/shared/vndk-core/libprotobuf-cpp-full.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libprotobuf-cpp-full.so
PRODUCT_COPY_FILES += \
prebuilts/vndk/v29/arm/arch-arm-armv7-a-neon/shared/vndk-core/libprotobuf-cpp-full.so:$(TARGET_COPY_OUT_VENDOR)/lib/libprotobuf-cpp-full.so \
prebuilts/vndk/v29/arm64/arch-arm64-armv8-a/shared/vndk-core/libprotobuf-cpp-full.so:$(TARGET_COPY_OUT_VENDOR)/lib64/libprotobuf-cpp-full.so
# QTI # QTI
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
@ -458,13 +411,11 @@ PRODUCT_PACKAGES += \
# Sensors # Sensors
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.sensors@2.0.vendor \ android.hardware.sensors@2.0.vendor \
libsensorndkbridge \ libsensorndkbridge
android.frameworks.sensorservice@1.0.vendor
# Soong namespaces # Soong namespaces
PRODUCT_SOONG_NAMESPACES += \ PRODUCT_SOONG_NAMESPACES += \
$(LOCAL_PATH) \ $(LOCAL_PATH) \
hardware/xiaomi \
hardware/google/interfaces \ hardware/google/interfaces \
hardware/google/pixel \ hardware/google/pixel \
vendor/qcom/opensource/commonsys/system/bt/conf \ vendor/qcom/opensource/commonsys/system/bt/conf \
@ -480,8 +431,8 @@ PRODUCT_ALWAYS_PREOPT_EXTRACTED_APK := true
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
telephony-ext telephony-ext
#PRODUCT_BOOT_JARS += \ PRODUCT_BOOT_JARS += \
# telephony-ext telephony-ext
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
qti-telephony-hidl-wrapper \ qti-telephony-hidl-wrapper \
@ -493,20 +444,21 @@ PRODUCT_PACKAGES += \
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
TetheringConfigOverlay TetheringConfigOverlay
# Thermal # Thermal engine
PRODUCT_PACKAGES += \
android.hardware.thermal@2.0-service.mock
PRODUCT_COPY_FILES += \ PRODUCT_COPY_FILES += \
$(LOCAL_PATH)/configs/thermal-engine.conf:$(TARGET_COPY_OUT_VENDOR)/etc/thermal-engine.conf $(LOCAL_PATH)/configs/thermal-engine.conf:$(TARGET_COPY_OUT_VENDOR)/etc/thermal-engine.conf
# TinyXML
PRODUCT_PACKAGES += \
libtinyxml
# Tracing # Tracing
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.atrace@1.0-service.pixel android.hardware.atrace@1.0-service.pixel
# USB # USB
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.usb@1.3-service.dual_role_usb android.hardware.usb@1.0-service
# Vibrator # Vibrator
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
@ -517,7 +469,7 @@ PRODUCT_COPY_FILES += \
# WiFi # WiFi
PRODUCT_PACKAGES += \ PRODUCT_PACKAGES += \
android.hardware.wifi-service \ android.hardware.wifi@1.0-service \
hostapd \ hostapd \
libwifi-hal-qcom \ libwifi-hal-qcom \
libwpa_client \ libwpa_client \
@ -538,8 +490,14 @@ PRODUCT_PACKAGES += \
libnl \ libnl \
libwfdaac_vendor libwfdaac_vendor
# Setting vendor SPL
VENDOR_SECURITY_PATCH = $(PLATFORM_SECURITY_PATCH)
# Set boot SPL
BOOT_SECURITY_PATCH = $(PLATFORM_SECURITY_PATCH)
# App launch prefetching (IORapd) # App launch prefetching (IORapd)
PRODUCT_SYSTEM_PROPERTIES += \ PRODUCT_PROPERTY_OVERRIDES += \
ro.iorapd.enable=false \ ro.iorapd.enable=false \
iorapd.perfetto.enable=false \ iorapd.perfetto.enable=false \
iorapd.readahead.enable=false \ iorapd.readahead.enable=false \

1
sepolicy/private/init.te Normal file
View file

@ -0,0 +1 @@
allow init proc:file write;

View file

@ -1,2 +0,0 @@
allow odrefresh self:capability kill;
allow odrefresh aac_drc_prop:file { getattr open };

View file

@ -1,6 +1,7 @@
type fingerprint_data_file, data_file_type, file_type; type fingerprint_data_file, data_file_type, file_type;
type thermal_data_file, data_file_type, file_type; type thermal_data_file, data_file_type, file_type;
type debugfs_sched_features, debugfs_type, fs_type;
type proc_sysctl_schedboost, proc_type, fs_type; type proc_sysctl_schedboost, proc_type, fs_type;
type sysfs_fingerprint, sysfs_type, fs_type; type sysfs_fingerprint, sysfs_type, fs_type;

View file

@ -13,13 +13,11 @@
# HALs # HALs
/vendor/bin/hw/android\.hardware\.light@2\.0-service\.lenovo_sdm710 u:object_r:hal_light_default_exec:s0 /vendor/bin/hw/android\.hardware\.light@2\.0-service\.lenovo_sdm710 u:object_r:hal_light_default_exec:s0
#/vendor/bin/hw/android\.hardware\.power@1\.3-service\.lenovo-libperfmgr u:object_r:hal_power_default_exec:s0 /vendor/bin/hw/android\.hardware\.power@1\.3-service\.lenovo-libperfmgr u:object_r:hal_power_default_exec:s0
#/vendor/bin/hw/android\.hardware\.power-service\.lenovo-sdm710-libperfmgr u:object_r:hal_power_default_exec:s0 /vendor/bin/hw/android\.hardware\.power-service\.lenovo-sdm710-libperfmgr u:object_r:hal_power_default_exec:s0
/vendor/bin/hw/android\.hardware\.power-service\.xiaomi-libperfmgr u:object_r:hal_power_default_exec:s0 /vendor/bin/hw/android\.hardware\.biometrics\.fingerprint@2\.1-fpcservice u:object_r:hal_fingerprint_default_exec:s0
/vendor/bin/hw/android\.hardware\.biometrics\.fingerprint-service\.xiaomi u:object_r:hal_fingerprint_default_exec:s0
/vendor/bin/hw/android\.hardware\.atrace@1.0-service\.pixel u:object_r:hal_atrace_default_exec:s0 /vendor/bin/hw/android\.hardware\.atrace@1.0-service\.pixel u:object_r:hal_atrace_default_exec:s0
/vendor/bin/hw/android\.hardware\.neuralnetworks@1\.2-service-qti u:object_r:hal_neuralnetworks_default_exec:s0 /vendor/bin/hw/android\.hardware\.neuralnetworks@1\.2-service-qti u:object_r:hal_neuralnetworks_default_exec:s0
/(vendor|system/vendor)/bin/hw/android\.hardware\.thermal@2\.0-service\.mock u:object_r:hal_thermal_default_exec:s0
# Allystar GPS # Allystar GPS
/sys/ontim_bootinfo/gps_avdd_en u:object_r:sysfs_gps:s0 /sys/ontim_bootinfo/gps_avdd_en u:object_r:sysfs_gps:s0
@ -33,3 +31,7 @@
# Block devices # Block devices
/dev/block/platform/soc/7c4000\.sdhci/by-name/system u:object_r:system_block_device:s0 /dev/block/platform/soc/7c4000\.sdhci/by-name/system u:object_r:system_block_device:s0
/dev/block/platform/soc/7c4000\.sdhci/by-name/vendor u:object_r:system_block_device:s0 /dev/block/platform/soc/7c4000\.sdhci/by-name/vendor u:object_r:system_block_device:s0
/dev/block/platform/soc/7c4000\.sdhci/by-name/logdump u:object_r:metadata_block_device:s0
# MMC
/sys/devices/platform/soc/7c4000.sdhci/mmc_host/mmc0/mmc0:0001/block/mmcblk0/queue/discard_max_bytes u:object_r:sysfs_mmc_host:s0

View file

@ -1,3 +1 @@
type vendor_persist_block_device, dev_type; allow fsck fsck:capability kill;
allow fsck self:capability { sys_admin kill };

View file

@ -1,12 +1,13 @@
genfscon sysfs /power/rpmh_stats/master_stats u:object_r:sysfs_rpm:s0 genfscon sysfs /power/rpmh_stats/master_stats u:object_r:sysfs_rpm:s0
genfscon sysfs /power/system_sleep/stats u:object_r:sysfs_system_sleep_stats:s0 genfscon sysfs /power/system_sleep/stats u:object_r:sysfs_system_sleep_stats:s0
genfscon debugfs /sched_features u:object_r:debugfs_sched_features:s0
genfscon proc /sys/kernel/sched_boost u:object_r:proc_sysctl_schedboost:s0 genfscon proc /sys/kernel/sched_boost u:object_r:proc_sysctl_schedboost:s0
# DT2W # DT2W
genfscon sysfs /devices/virtual/touch/tp_dev/gesture_on u:object_r:sysfs_tp:s0 genfscon sysfs /devices/virtual/touch/tp_dev/gesture_on u:object_r:sysfs_tp:s0
# Graphics # Graphics
genfscon sysfs /sys/devices/platform/soc/soc:qcom,msm-ext-disp/extcon/extcon1/name u:object_r:sysfs_graphics:s0 genfscon sysfs /devices/platform/soc/soc:qcom,msm-ext-disp/extcon/extcon1/name u:object_r:sysfs_graphics:s0
genfscon sysfs /sys/devices/platform/soc/soc:qcom,msm-ext-disp/extcon/extcon2/name u:object_r:sysfs_graphics:s0 genfscon sysfs /devices/platform/soc/soc:qcom,msm-ext-disp/extcon/extcon2/name u:object_r:sysfs_graphics:s0
genfscon sysfs /sys/devices/platform/soc/soc:qcom,msm-ext-disp/extcon/extcon3/name u:object_r:sysfs_graphics:s0 genfscon sysfs /devices/platform/soc/soc:qcom,msm-ext-disp/extcon/extcon3/name u:object_r:sysfs_graphics:s0

View file

@ -16,6 +16,7 @@ allow hal_power_default sysfs_devices_system_cpu:file rw_file_perms;
allow hal_power_default device_latency:chr_file rw_file_perms; allow hal_power_default device_latency:chr_file rw_file_perms;
allow hal_power_default cgroup:dir search; allow hal_power_default cgroup:dir search;
allow hal_power_default cgroup:file rw_file_perms; allow hal_power_default cgroup:file rw_file_perms;
allow hal_power_default debugfs_sched_features:file rw_file_perms;
allow hal_power_default proc_sysctl_schedboost:file rw_file_perms; allow hal_power_default proc_sysctl_schedboost:file rw_file_perms;
# Allow power hal to talk to mm-pp-daemon to control display lpm # Allow power hal to talk to mm-pp-daemon to control display lpm

View file

@ -4,5 +4,3 @@ allow init logdump_partition:lnk_file relabelto;
allow init self:netlink_route_socket rw_socket_perms_no_ioctl; allow init self:netlink_route_socket rw_socket_perms_no_ioctl;
allow init self:rawip_socket create_socket_perms_no_ioctl; allow init self:rawip_socket create_socket_perms_no_ioctl;
allow init socket_device:sock_file { unlink setattr create }; allow init socket_device:sock_file { unlink setattr create };
allow init proc:file write;

View file

@ -1 +0,0 @@
allow mediacodec vendor_audio_prop:file { read open getattr map };

View file

@ -1,12 +1,3 @@
# Audio
audio_hal. u:object_r:vendor_audio_prop:s0
audio.offload.buffer.size.kb u:object_r:vendor_audio_prop:s0
audio.offload.gapless.enabled u:object_r:vendor_audio_prop:s0
persist.audio.fluence.speaker u:object_r:vendor_audio_prop:s0
persist.audio.fluence.voicecall u:object_r:vendor_audio_prop:s0
persist.audio.fluence.voicerec u:object_r:vendor_audio_prop:s0
ro.qc.sdk.audio.fluencetype u:object_r:vendor_audio_prop:s0
# Camera # Camera
camera. u:object_r:camera_prop:s0 camera. u:object_r:camera_prop:s0
persist.camera. u:object_r:camera_prop:s0 persist.camera. u:object_r:camera_prop:s0
@ -26,9 +17,6 @@ vendor.powerhal.init u:object_r:vendor_power_prop:s0
vendor.powerhal.rendering u:object_r:vendor_power_prop:s0 vendor.powerhal.rendering u:object_r:vendor_power_prop:s0
vendor.powerhal.dalvik. u:object_r:vendor_power_prop:s0 vendor.powerhal.dalvik. u:object_r:vendor_power_prop:s0
# Fastbootd
ro.fastbootd.available u:object_r:exported_default_prop:s0
# Thermal # Thermal
persist.sys.thermal. u:object_r:thermal_engine_prop:s0 persist.sys.thermal. u:object_r:thermal_engine_prop:s0

View file

@ -1,5 +1,3 @@
# Allow rild to read, write and create files in vendor_data_file # Allow rild to read, write and create files in vendor_data_file
allow rild vendor_data_file:dir rw_dir_perms; allow rild vendor_data_file:dir rw_dir_perms;
allow rild vendor_data_file:file create_file_perms; allow rild vendor_data_file:file create_file_perms;
binder_call(rild, qtidataservices_app)

View file

@ -1,2 +1 @@
allow tee tmpfs:dir r_dir_perms; allow tee tmpfs:dir r_dir_perms;
allow tee persist_file:lnk_file read;

View file

@ -1 +0,0 @@
allow vdc self:capability kill;

View file

@ -2,7 +2,6 @@ set_prop(vendor_init, vendor_power_prop)
set_prop(vendor_init, freq_prop) set_prop(vendor_init, freq_prop)
get_prop(vendor_init, persist_debug_prop) get_prop(vendor_init, persist_debug_prop)
set_prop(vendor_init, vendor_bluetooth_prop)
# Allow vendor_init to write to sysfs_ssr_toggl # Allow vendor_init to write to sysfs_ssr_toggl
allow vendor_init sysfs_ssr_toggle:file w_file_perms; allow vendor_init sysfs_ssr_toggle:file w_file_perms;

View file

@ -1,24 +0,0 @@
# Bluetooth
vendor.qcom.bluetooth.soc=cherokee
# Audio
persist.vendor.bt.a2dp_offload_cap=sbc-aptx-aptxhd-aac-ldac
# Multi-gen LRU
persist.device_config.mglru_native.lru_gen_config=all
# Graphics
ro.hwui.render_ahead=20
# System Server
arm64.memtag.process.system_server=off
# Radio Powersaving
persist.radio.add_power_save=1
pm.sleep_mode=1
ro.ril.disable.power.collapse=0
ro.ril.fast.dormancy.rule=1
ro.ril.fast.dormancy.timeout=3
ro.mot.eri.losalert.delay=100
ro.vold.umsdirtyratio=20
power.saving.mode=1

View file

@ -82,6 +82,7 @@ vendor.audio.feature.snd_mon.enable=true
vendor.voice.path.for.pcm.voip=true vendor.voice.path.for.pcm.voip=true
# Bluetooth # Bluetooth
vendor.bluetooth.soc=cherokee
bluetooth.device.class_of_device=90,2,12 bluetooth.device.class_of_device=90,2,12
bluetooth.hardware.power.operating_voltage_mv=3300 bluetooth.hardware.power.operating_voltage_mv=3300
bluetooth.profile.asha.central.enabled?=true bluetooth.profile.asha.central.enabled?=true
@ -122,30 +123,32 @@ debug.sf.phase_offset_threshold_for_next_vsync_ns=6100000
# Graphics # Graphics
debug.sf.auto_latch_unsignaled=true debug.sf.auto_latch_unsignaled=true
ro.hwui.render_ahead=20
debug.hwui.renderer=opengl debug.hwui.renderer=opengl
# Fastbootd
ro.fastbootd.available=true
# Factory Reset Protection # Factory Reset Protection
ro.frp.pst=/dev/block/bootdevice/by-name/frp ro.frp.pst=/dev/block/bootdevice/by-name/frp
# FUSE passthrough
persist.sys.fuse.passthrough.enable=true
# FS-verity # FS-verity
ro.apk_verity.mode=2 ro.apk_verity.mode=2
# Media # Media
debug.stagefright.omx_default_rank=0 debug.stagefright.omx_default_rank=0
# NetMgr
ro.telephony.iwlan_operation_mode=legacy
# Perf # Perf
ro.vendor.extension_library=libqti-perfd-client.so ro.vendor.extension_library=libqti-perfd-client.so
ro.vendor.perf.scroll_opt=true ro.vendor.perf.scroll_opt=true
# Multi-gen LRU
persist.device_config.mglru_native.lru_gen_config=all
# Radio # Radio
ro.carrier=unknown ro.carrier=unknown
persist.radio.multisim.config=dsds persist.radio.multisim.config=dsds
persist.vendor.qti.telephony.vt_cam_interface=2
persist.vendor.radio.add_power_save=1 persist.vendor.radio.add_power_save=1
persist.vendor.radio.apm_sim_not_pwdn=1 persist.vendor.radio.apm_sim_not_pwdn=1
persist.vendor.radio.sib16_support=1 persist.vendor.radio.sib16_support=1
@ -159,6 +162,9 @@ persist.vendor.radio.mt_sms_ack=30
ro.soc.manufacturer=QTI ro.soc.manufacturer=QTI
ro.soc.model=SDM710 ro.soc.model=SDM710
# System Server
arm64.memtag.process.system_server=off
# Target specific Netflix custom property # Target specific Netflix custom property
ro.netflix.bsp_rev=Q855-16947-1 ro.netflix.bsp_rev=Q855-16947-1

View file

@ -125,6 +125,10 @@ gChannelBondingMode5GHz=1
gGoKeepAlivePeriod = 20 gGoKeepAlivePeriod = 20
gApKeepAlivePeriod = 20 gApKeepAlivePeriod = 20
#If set will start with active scan after driver load, otherwise will start with
#passive scan to find out the domain
gEnableBypass11d=1
#If set to 0, will not scan DFS channels #If set to 0, will not scan DFS channels
gEnableDFSChnlScan=1 gEnableDFSChnlScan=1
@ -196,8 +200,8 @@ gEnableFastRoamInConcurrency=1
# 802.11K support # 802.11K support
gRrmEnable=1 gRrmEnable=1
#Enable Optimized Power Management #Enable Power Save offload
gOptimizedPowerManagement=1 gEnablePowerSaveOffload=4
#Enable firmware uart print #Enable firmware uart print
gEnablefwprint=0 gEnablefwprint=0