├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ └── feature_request.yml └── workflows │ ├── build.yml │ ├── releases.yml │ └── sync-gitee.yml ├── CMakeLists.txt ├── Changelog_All.md ├── LICENSE ├── README.md ├── inc ├── foreground_app.h ├── global.h ├── main.h ├── my_malloc.h ├── my_thread.h ├── options_linkedlist.h ├── printf_with_time.h ├── read_option_file.h ├── some_ctrl.h └── value_set.h ├── module ├── META-INF │ └── com │ │ └── google │ │ └── android │ │ ├── update-binary │ │ └── updater-script ├── common │ ├── bypass_charge.txt │ ├── option.txt │ ├── service.sh │ └── uninstall.sh ├── customize.sh └── module.prop ├── src ├── foreground_app.c ├── global.c ├── main.c ├── my_malloc.c ├── my_thread.c ├── options_linkedlist.c ├── printf_with_time.c ├── read_option_file.c ├── some_ctrl.c └── value_set.c └── update_channel ├── changelog.md ├── turbo-charge.json └── turbo-charge.zip /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: BUG反馈 2 | description: 反馈错误或异常行为。 3 | labels: [bug] 4 | title: "[BUG] " 5 | body: 6 | - type: checkboxes 7 | id: latest 8 | attributes: 9 | label: 版本要求 10 | options: 11 | - label: 我正在使用[Releases](https://github.com/chase535/turbo-charge/releases)中的最新版本 12 | required: true 13 | - type: textarea 14 | attributes: 15 | label: 复现步骤 16 | placeholder: 此BUG会在什么情况下复现 17 | validations: 18 | required: true 19 | - type: textarea 20 | attributes: 21 | label: 预期行为 22 | placeholder: 正常情况下应该发生什么 23 | validations: 24 | required: true 25 | - type: textarea 26 | attributes: 27 | label: 实际行为 28 | placeholder: 实际上发生了什么 29 | validations: 30 | required: true 31 | - type: input 32 | attributes: 33 | label: 安卓版本 34 | validations: 35 | required: true 36 | - type: input 37 | attributes: 38 | label: 手机系统及版本 39 | validations: 40 | required: true 41 | - type: textarea 42 | attributes: 43 | label: 附件 44 | placeholder: 如有附件请点击文本框后上传。 45 | validations: 46 | required: false 47 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 适配不支持的机型 4 | url: https://github.com/chase535/turbo-charge/issues/84#issuecomment-1591033332 5 | about: 适配需要文件,但问题就在这,我也不知道需要哪些文件,之前收集过很多不适配的手机的各种文件,但是发现并没有需要的文件,而且没有的很彻底,所以我也无从下手,无法进行适配。 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: 请求添加新功能或对程序进行改进 2 | description: 提出建议。 3 | labels: [enhancement] 4 | title: "[Feature Request] " 5 | body: 6 | - type: textarea 7 | attributes: 8 | label: 你的请求是否与某个问题相关? 9 | placeholder: 若相关请清晰准确地描述该问题,若无关请填“无”。 10 | validations: 11 | required: true 12 | - type: textarea 13 | attributes: 14 | label: 描述你想要的解决方案 15 | placeholder: 请清晰准确地描述新功能的预期行为或程序需要进行改进的地方 16 | validations: 17 | required: true 18 | - type: textarea 19 | attributes: 20 | label: 其他信息 21 | placeholder: 其他关于此请求的信息或截图,非必填 22 | validations: 23 | required: false 24 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - 'main' 8 | paths-ignore: 9 | - '**.md' 10 | - '**.zip' 11 | - '**.json' 12 | - '.github/ISSUE_TEMPLATE/**' 13 | pull_request: 14 | branches: 15 | - 'main' 16 | 17 | env: 18 | HOME: "${{ github.workspace }}" 19 | 20 | jobs: 21 | build: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - name: Checkout 25 | uses: actions/checkout@v4 26 | - name: Install tools 27 | run: | 28 | sudo apt-get update 29 | sudo apt-get install -y ssh git make cmake 30 | - name: Clone aarch64-linux-musl-gcc 31 | run: git clone https://github.com/chase535/aarch64-linux-musl-gcc.git ${HOME}/aarch64-linux-musl-gcc -b main --depth=1 32 | - name: Set C and C++ compiler 33 | run: | 34 | echo "CC=${HOME}/aarch64-linux-musl-gcc/bin/aarch64-linux-musl-gcc" >> ${GITHUB_ENV} 35 | echo "CXX=${HOME}/aarch64-linux-musl-gcc/bin/aarch64-linux-musl-g++" >> ${GITHUB_ENV} 36 | - name: Clone and build mimalloc 37 | run: | 38 | git clone https://github.com/microsoft/mimalloc.git ${HOME}/mimalloc -b dev3 39 | cd ${HOME}/mimalloc 40 | mimalloc_version="$(git describe --abbrev=0 --tags | sed "s|^v||g")" 41 | echo "MIMALLOC_VERSION=${mimalloc_version}" >> ${GITHUB_ENV} 42 | mkdir -p ${HOME}/mimalloc/out 43 | cd ${HOME}/mimalloc/out 44 | cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_NAME=Linux -DCMAKE_SYSTEM_PROCESSOR=aarch64 -DMI_BUILD_STATIC=ON -DMI_BUILD_SHARED=OFF -DMI_BUILD_OBJECT=OFF -DMI_BUILD_TESTS=OFF -DMI_SECURE=OFF 45 | make -j$(nproc --all) 46 | sudo make install -j$(nproc --all) 47 | - name: Build module 48 | run: | 49 | cmake -B build 50 | make -C build -j$(nproc --all) 51 | - name: Copy files into module directory 52 | run: | 53 | cp -f ${HOME}/README.md ${HOME}/LICENSE ${HOME}/module 54 | cp -f ${HOME}/build/turbo-charge ${HOME}/module/common 55 | - name : Zip and upload module 56 | uses: actions/upload-artifact@v4 57 | with: 58 | name: turbo-charge 59 | path: ${{ github.workspace }}/module/* 60 | -------------------------------------------------------------------------------- /.github/workflows/releases.yml: -------------------------------------------------------------------------------- 1 | name: Update Magisk Channel Data 2 | 3 | on: 4 | release: 5 | types: 6 | - 'published' 7 | 8 | env: 9 | GITHUB_USER: "${{ secrets.USERNAME }}" 10 | GITHUB_EMAIL: "${{ secrets.EMAIL }}" 11 | GITHUB_TOKEN: "${{ secrets.API_TOKEN_GITHUB }}" 12 | HOME: "${{ github.workspace }}" 13 | GIT_CLONE: "${{ github.workspace }}/git_clone" 14 | REF: "${{ github.ref }}" 15 | 16 | jobs: 17 | build: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - name: Checkout 21 | uses: actions/checkout@v4 22 | - name: Install tools 23 | run: | 24 | sudo apt-get update 25 | sudo apt-get install -y wget jq dos2unix ssh git zip 26 | - name: Get tag 27 | run: | 28 | tag=$(echo ${REF} | sed "s|refs/tags/||g") 29 | echo ${tag} 30 | echo "TAG=${tag}" >> ${GITHUB_ENV} 31 | - name: Wget zip file 32 | run: | 33 | wget -P ${HOME} https://github.com/chase535/turbo-charge/releases/download/${TAG}/turbo-charge.zip 34 | - name: Wget and parse releases json 35 | run: | 36 | versioncode=$(echo ${TAG} | sed "s|v||g") 37 | wget -P ${HOME} https://api.github.com/repos/chase535/turbo-charge/releases/tags/${TAG} -O releases.json 38 | cd ${HOME} 39 | jq -rM '.body' ./releases.json > ./changelog.md 40 | cp -avf ./changelog.md ./changelog_body.md 41 | sed -i "1i # ${TAG}" ./changelog.md 42 | sed -i G ./changelog.md 43 | echo "{\"version\": \"${TAG}\",\"versionCode\": \"${versioncode}\"}" > ./version.json 44 | - name: Modified files 45 | run: | 46 | git config --global user.name "${GITHUB_USER}" 47 | git config --global user.email "${GITHUB_EMAIL}" 48 | git clone https://"${GITHUB_USER}":"${GITHUB_TOKEN}"@github.com/chase535/turbo-charge.git ${GIT_CLONE} -b main --depth=1 49 | cd ${HOME} 50 | cp -avf ./changelog.md ./Changelog_All.md 51 | cat ${GIT_CLONE}/Changelog_All.md >> ./Changelog_All.md 52 | dos2unix ./changelog.md ./changelog_body.md ./Changelog_All.md 53 | cp -avf ./changelog.md ${GIT_CLONE}/update_channel 54 | cp -avf ./Changelog_All.md ${GIT_CLONE} 55 | jq -sM add ${GIT_CLONE}/update_channel/turbo-charge.json ./version.json > ./turbo-charge.json 56 | dos2unix ./turbo-charge.json 57 | cp -avf ./turbo-charge.json ./turbo-charge.zip ${GIT_CLONE}/update_channel 58 | - name: Add changelog.md into zip file 59 | run: | 60 | cd ${GIT_CLONE} 61 | zip -u ./update_channel/turbo-charge.zip Changelog_All.md 62 | - name: Push 63 | run: | 64 | cd ${GIT_CLONE} 65 | git add . -f 66 | git commit -a -m "更新${TAG}版本" 67 | git push origin main -f 68 | - name: Update release 69 | uses: softprops/action-gh-release@v1 70 | with: 71 | token: ${{ secrets.API_TOKEN_GITHUB }} 72 | tag_name: ${{ env.TAG }} 73 | files: ${{ env.GIT_CLONE }}/update_channel/turbo-charge.zip 74 | body_path: ${{ env.HOME }}/changelog_body.md 75 | generate_release_notes: false 76 | -------------------------------------------------------------------------------- /.github/workflows/sync-gitee.yml: -------------------------------------------------------------------------------- 1 | name: Sync To Gitee 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - 'main' 8 | 9 | env: 10 | SSH_PRIVATE_KEY: "${{ secrets.SSH_PRIVATE_KEY }}" 11 | GIT_CLONE: "${{ github.workspace }}/git_clone" 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | with: 20 | fetch-depth: 0 21 | - name: Install tools 22 | run: | 23 | sudo apt-get update 24 | sudo apt-get install -y ssh git 25 | - name: Sync to Gitee 26 | run: | 27 | mkdir -p ~/.ssh 28 | echo "${SSH_PRIVATE_KEY}" > ~/.ssh/id_rsa 29 | sudo chmod 0600 ~/.ssh/id_rsa 30 | sudo chmod 0777 /etc/ssh/ssh_config 31 | sudo echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config 32 | sudo chmod 0644 /etc/ssh/ssh_config 33 | eval "$(ssh-agent -s)" 34 | ssh-add ~/.ssh/id_rsa 35 | mkdir -vp ${GIT_CLONE} 36 | git clone --mirror "git@github.com:chase535/turbo-charge.git" ${GIT_CLONE} 37 | cd ${GIT_CLONE} 38 | git remote set-url --push origin "git@gitee.com:chase535/turbo-charge" 39 | git fetch -p origin 40 | git for-each-ref --format 'delete %(refname)' refs/pull | git update-ref --stdin 41 | git push --mirror 42 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMake最低版本号要求 2 | cmake_minimum_required(VERSION 3.14) 3 | 4 | # 项目信息 5 | project(turbo-charge) 6 | 7 | # 配置环境 8 | set(CMAKE_SYSTEM_NAME "Linux") 9 | set(CMAKE_SYSTEM_PROCESSOR "aarch64") 10 | 11 | # 发行版本 12 | set(CMAKE_BUILD_TYPE "Release") 13 | 14 | # 设置编译链接参数 15 | set(CMAKE_C_FLAGS "-g0 -O2 -W -Wall -Wno-format-truncation -Wno-unused-result -Werror -fvisibility=hidden -flto -fno-omit-frame-pointer -fdata-sections -ffunction-sections") 16 | set(CMAKE_EXE_LINKER_FLAGS "-g0 -O2 -static -fvisibility=hidden -flto -ffixed-x18 -Wl,-O2,--strip-all,--hash-style=both,--gc-sections,--exclude-libs,ALL") 17 | 18 | # 查找mimalloc包 19 | if(DEFINED ENV{MIMALLOC_VERSION}) 20 | message(STATUS "'MIMALLOC_VERSION' is defined in the environment variable, find mimalloc version $ENV{MIMALLOC_VERSION}") 21 | find_package(MIMALLOC NO_SYSTEM_ENVIRONMENT_PATH $ENV{MIMALLOC_VERSION}) 22 | else() 23 | message(STATUS "'MIMALLOC_VERSION' is not defined in the environment variable, find any usable mimalloc version") 24 | find_package(MIMALLOC NO_SYSTEM_ENVIRONMENT_PATH) 25 | endif() 26 | if(MIMALLOC_FOUND) 27 | message(STATUS "Find mimalloc installed at: ${MIMALLOC_LIBRARY_DIR} (${MIMALLOC_VERSION_DIR}), use mimalloc") 28 | add_compile_definitions(MI_MALLOC) 29 | elseif(DEFINED ENV{MIMALLOC_VERSION}) 30 | message(STATUS "Could not find mimalloc version $ENV{MIMALLOC_VERSION}, use malloc") 31 | else() 32 | message(STATUS "Could not find any usable mimalloc, use malloc") 33 | endif() 34 | 35 | # 添加头文件目录 36 | include_directories(./inc) 37 | 38 | # 指定生成目标 39 | aux_source_directory(./src SRC_LIST) 40 | add_executable(turbo-charge ${SRC_LIST}) 41 | 42 | # 链接静态mimalloc库 43 | if(MIMALLOC_FOUND) 44 | target_link_libraries(turbo-charge PUBLIC mimalloc-static) 45 | endif() 46 | -------------------------------------------------------------------------------- /Changelog_All.md: -------------------------------------------------------------------------------- 1 | # v68 2 | 3 | ### Changelog 4 | 5 | 1.mimalloc切换为dev-slice分支 6 | 7 | 2.新增判断链表中是否有节点 8 | 9 | 3.优化代码 10 | 11 | # v67 12 | 13 | ### Changelog 14 | 15 | 1.修复一处未将位置指针重新指向stream开头的严重bug 16 | 17 | 2.优化代码 18 | 19 | # v66 20 | 21 | ### Changelog 22 | 23 | 1.不再使用bsd库函数strlcpy,使用glibc库函数strncpy并限制size 24 | 25 | 2.释放regex_t结构体,避免内存泄漏 26 | 27 | 3.优化代码 28 | 29 | # v65 30 | 31 | ### Changelog 32 | 33 | 1.cmake可通过定义环境变量MIMALLOC_VERSION来查找指定版本的mimalloc 34 | 35 | 2.将bypass_charge.txt文件中的内容加载至内存,仅在文件发生修改时才重新加载,而不是每次循环都直接读取本地文件,减少系统资源消耗 36 | 37 | 3.修复潜在的内存溢出问题 38 | 39 | 4.优化代码,提高程序运行效率 40 | 41 | # v64 42 | 43 | ### Changelog 44 | 45 | 1.推送通道更新日志仅显示当前版本,在模块压缩包中添加所有版本的更新日志 46 | 47 | 2.编译时CMake自动识别是否安装了mimalloc并使用不同的头文件及函数,函数部分使用函数指针实现 48 | 49 | 3.更改两处函数执行时机 50 | 51 | 4.优化代码 52 | 53 | # v61 54 | 55 | ### Changelog 56 | 57 | **开始上班,随缘更新** 58 | 59 | 1.使用[mimalloc](https://github.com/microsoft/mimalloc)代替原版malloc家族,以略微增加程序大小为代价,解决musl函数库malloc家族执行效率低的短板,提高程序运行效率 60 | 61 | 2.编译链接优化等级调整为2 62 | 63 | 3.安装及开机时`chattr -i`云控目录下的所有文件,提高兼容性 64 | 65 | 4.开机时将上次的运行日志文件重命名为log.txt.old 66 | 67 | # v60 68 | 69 | ### Changelog 70 | 71 | 1.使用链表代替数组来存储配置 72 | 73 | 2.使用设置函数属性+可变参数列表的全新方法打印时间 74 | 75 | 3.修复找不到部分文件夹时程序崩溃的BUG 76 | 77 | 4.优化文件大小 78 | 79 | 5.每次开机都尝试清空云控文件夹 80 | 81 | ~~优化代码 ✖~~ 82 | 83 | ~~炫技 ✔️~~ 84 | 85 | # v58 86 | 87 | ### Changelog 88 | 89 | 1.日常维护,优化代码 90 | 91 | 2.重命名并更新安装脚本,以兼容使用KernelSU安装 92 | 93 | 3.规范shell命令,将service.sh文件中的2>&1放在重定向标准输出之后 94 | 95 | # v55 96 | 97 | ### Changelog 98 | 99 | 1.使用另一种方式(define)来输出日期+文字 100 | 101 | 2.删除安装脚本一行多余的代码 102 | 103 | # v54 104 | 105 | ### Changelog 106 | 107 | 补充更新,不再使用source读取配置文件,修复无旧配置文件时安装失败的问题 108 | 109 | # v53 110 | 111 | ### Changelog 112 | 113 | 1.更新安装脚本,安装时保留原有的配置,不再使用音量键选择 114 | 115 | 2.修复配置文件禁用旁路供电后不会恢复充电电流的bug 116 | 117 | 3.读取配置文件改用子线程执行 118 | 119 | 4.添加互斥锁,多线程通信必备 120 | 121 | 5.修复潜在的无法读取文件的问题 122 | 123 | 6.优化代码 124 | 125 | # v52 126 | 127 | ### Changelog 128 | 129 | 1.添加“伪”旁路供电功能并添加相关日志 130 | 131 | 2.重构温度读取部分代码 132 | 133 | 3.优化大量代码 134 | 135 | 4.代码添加注释,现在小学二年级的同学都能看懂代码的思路了呢 136 | 137 | 我是干嵌入式系统开发的,不熟悉安卓内核及AndroidNDK,无法使用纯c语言实现,我没那个能力,所以用多线程+popen执行shell命令来获取前台应用信息。多线程是为了能够确保主程序的执行效率,因为shell是脚本语言,执行效率很低。 138 | 139 | “伪”旁路供电功能仅支持安卓7及以上的系统。之所以是“伪”旁路供电,是因为在不支持旁路供电的手机上无法实现真正的旁路供电,只能尽可能多的降低充电电流且充电电流无法降到0mA。具体查看[Linux内核文档的power_supply_class章节](https://www.kernel.org/doc/html/latest/power/power_supply_class.html)。在我手机上测试500mA是最低值,低于这个值的话限制无效,所以将“伪”旁路供电的充电电流设置为500mA。 140 | 141 | “伪”旁路供电功能的配置文件在/data/adb/turbo-charge/bypass_charge.txt,直接在此文件内输入需要“伪”旁路供电的应用的包名即可,一行一个。打开相应的应用会使模块的温控功能暂时失效。未经完全测试,如果日志没有提示该功能失效且开启后无效,请及时前往Github进行反馈。 142 | 143 | # v50 144 | 145 | ### Changelog 146 | 147 | 1新增“是否启用强制显示28℃”功能,默认启用,可在配置文件中进行修改 148 | 149 | 2.优化温度传感器选择流程,修复部分手机无法正常获取温度的BUG 150 | 151 | # v48 152 | 153 | ### Changelog 154 | 155 | 修改安装脚本执行顺序,安装时会有更好的观感 156 | 157 | # v47 158 | 159 | ### Changelog 160 | 161 | 1.将默认循环时间改为1秒,因为间隔时间越长,程序虽然越省电,但越有可能导致抢充电协议,使得手机疯狂断充 162 | 163 | 2.优化代码逻辑 164 | 165 | # v46 166 | 167 | ### Changelog 168 | 169 | 1.删除QQ群 170 | 171 | 2.修复一处缓冲区溢出 172 | 173 | 3.将循环时间添加进配置文件 174 | 175 | 4.添加更多判定 176 | 177 | 5.优化大量代码 178 | 179 | QQ群不知为何被群主解散,我自己的事都忙不过来,根本没有时间和精力去管这些事,我也不想管,所以就这样吧。 180 | 181 | # v44 182 | 183 | ### Changelog 184 | 185 | 1.修改传感器顺序 186 | 187 | 2.所有文件在写入数值前均先判断新数值与原数值是否相等,若不等才修改 188 | 189 | 3.读取配置文件时添加数值的判断,以减少BUG的产生 190 | 191 | 4.仅当配置文件更新时才获取新数据 192 | 193 | 5.所有文件换行符CRLF转LF 194 | 195 | # v43 196 | 197 | ### Changelog 198 | 199 | 修复部分手机打开电量控制到达阈值停止充电后无法再恢复充电的BUG 200 | 201 | # v42 202 | 203 | ### Changelog 204 | 205 | 开机完成后执行两次程序,间隔1分钟后杀死第一次执行的进程,以解决部分手机充电缓慢的BUG 206 | 207 | # v40 208 | 209 | ### Changelog 210 | 211 | 1.修复部分设备充电缓慢的问题 212 | 213 | 2.不充电时强制显示28度的温度阈值更改为45度 214 | 215 | 3.等待手机启动完毕再执行程序,以确保时间准确。若log文件只看到一行内容,请立即联系模块作者! 216 | 217 | # v39 218 | 219 | ### Changelog 220 | 221 | 1.安装时使用find命令代替ls命令查找温控文件,以解决部分手机安装后会在模块目录产生大量无用空文件夹的BUG 222 | 223 | 2.将循环间隔时间缩短为1秒,因为是C语言直接编译成机器语言,所以不用担心执行效率问题 224 | 225 | # v38 226 | 227 | ### Changelog 228 | 229 | 1.添加更多温度传感器,让更多手机能够安装,但因为每个传感器的位置不同,导致传感器温度与体感温度会有偏差甚至大相径庭,所以仅添加了几个偏差不那么大的传感器 230 | 231 | 2.因上述原因,程序会对传感器进行选择,优先使用手机中存在且偏差小的传感器 232 | 233 | 3.日志新增温度传感器名字 234 | 235 | 4.优化安装脚本代码 236 | 237 | 5.优化代码,优化逻辑 238 | 239 | # v37 240 | 241 | ### Changelog 242 | 243 | 1.缩小正则匹配文件范围,解决断充、充电缓慢问题,安装脚本的文件判断范围同步缩小 244 | 245 | 2.配置文件的最大电流改为50A(如果真的有充电电流这么高的手机发布,那锂电池应该就被淘汰了) 246 | 247 | 3.安装时重新将mi_thermald替换为空文件,以解决充电仍有温控的问题 248 | 249 | 4.优化代码,优化逻辑 250 | 251 | **注意,目前已知的所有内核映射到系统级的限流文件(三个)均已加入文件判断范围,如果还不支持,就是内核级的限流了,内核直接处理数据而不是读取文件内容,唯一途径是改内核,阶梯式充电同理,没有文件就代表数据直接在内核处理甚至写死。current_max、pd_current_max、hw_current_max等文件虽然是内核将充电IC数据读取出来后写入文件,然后再根据文件内容进行电流限制,可被修改,但是是有直接的硬件限制(这些文件中存储的就是这个硬件限制的值),若手机的充电电流超过了硬件的限制且硬件根据评估后判断此时的电池状态并不能提升充电电流,硬件就会启动保护程序直接断充,电流从0开始增加到硬件认为的应该有的充电电流,所以修改这些文件并没有什么用,甚至会造成断充、充电缓慢等问题** 252 | 253 | # v36 254 | 255 | ### Changelog 256 | 257 | 修改正则表达式,修复因匹配了不该匹配的文件导致的充电慢、断充问题 258 | 259 | # v35 260 | 261 | ### Changelog 262 | 263 | 修复因手机疯狂抢充电协议导致手机卡顿断充的严重性BUG 264 | 265 | # v34 266 | 267 | ### Changelog 268 | 269 | 1.弱化所有文件的必要性,只有当所有的所需文件均不存在时才安装失败/程序强制退出 270 | 271 | 2.使用C语言非标准库regex.h,使用正则表达式查找文件,而非指定文件名,解决电流文件查找不全的问题 272 | 273 | 3.新增更多电流文件,理论上电流调节支持更多机型 274 | 275 | 4.日志新增查找到的电流、温度文件 276 | 277 | 5.优化代码,优化逻辑,部分变量使用calloc和free动态申请内存空间,理论上优化内存占用 278 | 279 | 6.增加大量判定,尽可能包含每一种情况 280 | 281 | # v33 282 | 283 | ### Changelog 284 | 285 | 将Magisk内部更新通道切换为Gitee,极大提升更新体验。 286 | 287 | [Gitee](https://gitee.com/chase535/turbo-charge)将实时同步[GitHub](https://github.com/chase535/turbo-charge)的任何更改,但由于众所周知的原因,Gitee仅充当更新通道,我不会使用Gitee。 288 | 289 | # v32 290 | 291 | ### Changelog 292 | 293 | 1.添加QQ群号 294 | 295 | 2.新增log文件(/data/adb/turbo-charge/log.txt),包含文件检测、配置更新、拔插充电器、温度控制、电量控制等信息,时间为UTC+8 296 | 297 | 3.修复温度控制生效时电量控制失效的BUG 298 | 299 | 4.修复温度控制的一处严重逻辑错误 300 | 301 | 5.启用电量控制时,若停止充电阈值设为100,则等待涓流充电结束后才停止充电 302 | 303 | 6.所有文件读取时均会在读取失败后将文件权限改为0644后再次尝试读取 304 | 305 | 7.增加多处判定,尽可能的包含各种情况 306 | 307 | 8.优化大量代码,优化代码逻辑 308 | 309 | 9.更新配置文件注释、模块描述等 310 | 311 | # v29-v31 312 | 313 | 因为30、31版本均为修复29版本才有的BUG,所以合并更新日志 314 | 315 | ### Changelog 316 | 317 | 1.添加阶梯充电相关选项(安装时音量键选择以及option.txt中自行更改) 318 | 319 | 2.安装和运行时弱化必要文件检测,缺失非必要但程序完整运行需要的文件时显示相关信息。**安装时提示缺少必要文件的手机请勿尝试强制运行程序,程序内也判断了必要文件是否存在,如不存在将强制停止运行,也就是说,缺少必要文件是肯定无法运行程序的** 320 | 321 | 3.将相关信息存入/data/adb/turbo-charge/log.txt中,后续log.txt还将包含充电器拔插、配置更改、撞温度墙等信息(画饼要尽可能的大,但牙膏要一点一点的挤) 322 | 323 | 4.添加一处判定,当数据写入失败时修改文件权限为0644后重新尝试写入数据 324 | 325 | 5.安装失败时删除modules_update目录下的模块文件夹,已解决即使安装失败,重启手机后也会在Magisk中显示模块的BUG 326 | 327 | # v28 328 | 329 | ### Changelog 330 | 331 | 1.在模块安装以及程序运行时判断必要文件是否存在,若不存在,则证明不适配此手机,模块安装失败/程序强制停止运行 332 | 333 | 2.电量大于等于15%时才关闭阶梯充电,以解决健康状态不太好的电池在低电量时充电疯狂断充的问题(酷安@来回拉扯 提供问题产生原因,@这谁顶得住呢 复现,只经过我手机的测试,阈值为15%,所以就设置为15%,但实测将阶梯充电关闭的一小段时间内仍有几率造成1-2次的断充,但总比疯狂断充要好) 334 | 335 | 3.添加Magisk内部的更新通道,使用Cloudflare做代理,国内劣质网络环境也能正常检测、下载更新,只不过延迟较高 336 | 337 | 4.重写安装脚本,以适配使用Magisk自带的util_functions.sh脚本进行安装(要求Magisk版本大于20.4) 338 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published 637 | by the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # turbo-charge 2 | 3 | **开始上班,随缘更新** 4 | 5 | 酷安:[诺鸡鸭](https://www.coolapk.com/u/1145497) 6 | 7 | ## 模块功能 8 | 9 | 删除温控,关闭阶梯式充电,持续修改电池温度及充电电流,尽可能的让手机满血快充。配置文件在/data/adb/turbo-charge/option.txt,可以更改一些参数,日志文件为同目录的log.txt 10 | 11 | ## 使用到的工具 12 | 13 | 1.使用自己构建的[aarch64-linux-musl-gcc](https://github.com/chase535/aarch64-linux-musl-gcc)交叉编译工具链进行编译链接,静态链接更高效,程序大小相较于使用基于glibc函数库的gnu-gcc生成的程序来说大量减少 14 | 15 | 2.使用[mimalloc](https://github.com/microsoft/mimalloc)代替原版malloc家族,以略微增加程序大小为代价,解决musl函数库malloc家族执行效率低的短板,提高程序运行效率 16 | 17 | 3.使用[CMake](https://cmake.org)自动生成Makefile文件(别问,问就是懒,不想学Makefile) 18 | 19 | ## 适配 20 | 21 | **我并不会适配不支持的机型,但您可通过提交PR来主动适配,亦可通过提交PR来优化程序** 22 | 23 | 适配需要文件,但问题就在这,我也不知道需要哪些文件,之前收集过很多不适配的手机的各种文件,但是发现并没有需要的文件,而且没有的很彻底,所以我无从下手,无法进行适配 24 | 25 | ## CI构建 26 | 27 | 已经开启CI构建,可在[Actions页面](https://github.com/chase535/turbo-charge/actions)下载CI构建版本以获取最新测试版,**不保证CI构建版本的功能性及稳定性** 28 | 29 | ## 开源协议 30 | 31 | 程序遵循**AGPLv3**开源协议 32 | -------------------------------------------------------------------------------- /inc/foreground_app.h: -------------------------------------------------------------------------------- 1 | #ifndef _FOREGROUND_APP_H 2 | #define _FOREGROUND_APP_H 3 | 4 | #include "main.h" 5 | 6 | extern volatile char ForegroundAppName[APP_PACKAGE_NAME_MAX_SIZE]; 7 | 8 | void *get_foreground_appname(void *android_version); 9 | int check_android_version(); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /inc/global.h: -------------------------------------------------------------------------------- 1 | #ifndef _GLOBAL_H 2 | #define _GLOBAL_H 3 | 4 | #define BYPASS_CHARGE_CURRENT "500000" 5 | #define APP_PACKAGE_NAME_MAX_SIZE 100 6 | 7 | extern char option_file[]; 8 | extern char bypass_charge_file[]; 9 | extern char temp_sensors[][15]; 10 | extern char temp_sensor_quantity; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /inc/main.h: -------------------------------------------------------------------------------- 1 | #ifndef _MAIN_H 2 | #define _MAIN_H 3 | 4 | #include "global.h" 5 | #include "options_linkedlist.h" 6 | #include "my_thread.h" 7 | 8 | typedef unsigned char uchar; 9 | typedef unsigned int uint; 10 | 11 | int list_dir(char *path, char ***ppp); 12 | void line_feed(char *line); 13 | void check_read_file(char *file); 14 | void read_file(char *file_path, char *char_var, int max_char_num); 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /inc/my_malloc.h: -------------------------------------------------------------------------------- 1 | #ifndef _MY_MALLOC_H 2 | #define _MY_MALLOC_H 3 | 4 | extern void *(*my_calloc)(size_t, size_t); 5 | extern void *(*my_realloc)(void *, size_t); 6 | extern void (*my_free)(void *); 7 | 8 | void free_malloc_memory(char ***addr, int num); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /inc/my_thread.h: -------------------------------------------------------------------------------- 1 | #ifndef _MY_THREAD_H 2 | #define _MY_THREAD_H 3 | 4 | #include 5 | 6 | extern volatile pthread_mutex_t mutex_foreground_app,mutex_options; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /inc/options_linkedlist.h: -------------------------------------------------------------------------------- 1 | #ifndef _OPTIONS_LINKEDLIST_H 2 | #define _OPTIONS_LINKEDLIST_H 3 | 4 | #define OPTION_NAME_MAX_SIZE 40 5 | 6 | typedef struct ListNode 7 | { 8 | char name[OPTION_NAME_MAX_SIZE]; 9 | volatile int value; 10 | struct ListNode *next; 11 | } ListNode; 12 | 13 | extern ListNode options_head; 14 | 15 | void insert_all_option(); 16 | int read_one_option(char *name); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /inc/printf_with_time.h: -------------------------------------------------------------------------------- 1 | #ifndef _PRINTF_WITH_TIME_H 2 | #define _PRINTF_WITH_TIME_H 3 | 4 | #include "main.h" 5 | 6 | void printf_with_time(const char *format, ...); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /inc/read_option_file.h: -------------------------------------------------------------------------------- 1 | #ifndef _READ_OPTION_FILE_H 2 | #define _READ_OPTION_FILE_H 3 | 4 | #include "main.h" 5 | 6 | void *read_option_file(void *arg); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /inc/some_ctrl.h: -------------------------------------------------------------------------------- 1 | #ifndef _SOME_CTRL_H 2 | #define _SOME_CTRL_H 3 | 4 | #include "main.h" 5 | 6 | void step_charge_ctl(char *value); 7 | void charge_ctl(char *i); 8 | void powel_ctl(int *last_charge_stop, int *charge_is_stop); 9 | void bypass_charge_ctl(pthread_t *thread1, int *android_version, char *last_appname, int *is_bypass, int *screen_is_off, char **current_max_file, int current_max_file_num); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /inc/value_set.h: -------------------------------------------------------------------------------- 1 | #ifndef _VALUE_SET_H 2 | #define _VALUE_SET_H 3 | 4 | #include "main.h" 5 | 6 | void set_value(char *file, char *numb); 7 | void set_array_value(char **file, int num, char *value); 8 | void set_temp(char *temp_sensor, char **temp_file, int temp_file_num, uchar tempwall); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /module/META-INF/com/google/android/update-binary: -------------------------------------------------------------------------------- 1 | #!/sbin/sh 2 | 3 | ################# 4 | # Initialization 5 | ################# 6 | 7 | umask 022 8 | 9 | # echo before loading util_functions 10 | ui_print() { echo "$1"; } 11 | 12 | require_new_magisk() { 13 | ui_print "*******************************" 14 | ui_print " Please install Magisk v20.4+! " 15 | ui_print "*******************************" 16 | exit 1 17 | } 18 | 19 | ######################### 20 | # Load util_functions.sh 21 | ######################### 22 | 23 | OUTFD=$2 24 | ZIPFILE=$3 25 | 26 | mount /data 2>/dev/null 27 | 28 | [ -f /data/adb/magisk/util_functions.sh ] || require_new_magisk 29 | . /data/adb/magisk/util_functions.sh 30 | [ $MAGISK_VER_CODE -lt 20400 ] && require_new_magisk 31 | 32 | install_module 33 | exit 0 34 | -------------------------------------------------------------------------------- /module/META-INF/com/google/android/updater-script: -------------------------------------------------------------------------------- 1 | #MAGISK 2 | -------------------------------------------------------------------------------- /module/common/bypass_charge.txt: -------------------------------------------------------------------------------- 1 | #之所以是“伪”旁路供电,是因为在不支持旁路供电的手机上无法实现真正的旁路供电,只能尽可能多的降低充电电流且充电电流无法降到0mA 2 | #具体看linux内核的相关文档:https://www.kernel.org/doc/html/latest/power/power_supply_class.html 3 | #在我手机上测试500mA是最低值,低于这个值的话限制无效,所以将“伪”旁路供电的充电电流设置为500mA 4 | 5 | #直接在此文件内输入需要“伪”旁路供电的应用的包名即可 6 | #打开相应的应用会使模块的温控功能暂时失效 7 | #未经完全测试,如果日志没有提示该功能失效且开启后无效,请及时前往Github进行反馈 8 | #一行一个,实时生效 9 | 10 | -------------------------------------------------------------------------------- /module/common/option.txt: -------------------------------------------------------------------------------- 1 | #配置更改实时生效 2 | #CYCLE_TIME必须大于0,其他配置必须大于等于0 3 | #所有配置都必须为整数,且最大可设为2147483647,若超过此值,会出现BUG(具体原因自行百度) 4 | 5 | #循环间隔时间(单位:s) 6 | #默认为1秒,不建议大于5秒 7 | #间隔时间越长,程序越省电,但越有可能导致抢充电协议,使得手机疯狂断充 8 | CYCLE_TIME=1 9 | 10 | #是否启用强制显示28℃功能(1为启用,其他数字为禁用) 11 | #在开启强制显示28℃功能时有以下限制,以避免温度过高手机卡顿甚至强制关机 12 | #若不充电时手机温度大于等于45℃,程序仍会强制显示28℃ 13 | #等待手机温度降至45℃以下,显示真实温度 14 | FORCE_TEMP=1 15 | 16 | #最大充电电流(单位:μA。经测试超过手机理论最大充电电流不会出现bug,所以保持默认即可) 17 | CURRENT_MAX=50000000 18 | 19 | #是否关闭阶梯式充电(1为关闭,其他数字为不关闭) 20 | STEP_CHARGING_DISABLED=0 21 | #是否添加温控(1为添加,其他数字为不添加) 22 | TEMP_CTRL=1 23 | #是否添加电量控制(1为添加,其他数字为不添加) 24 | POWER_CTRL=0 25 | 26 | #此配置关闭阶梯式充电时生效 27 | #关闭阶梯式充电的电量阈值(电量大于等于此值时关闭阶梯式充电,整数) 28 | #阶梯式充电状态切换时有几率造成1-2次的断充 29 | #注意,某些手机电池健康状态不好时关闭阶梯式充电后电量低于15%时充电会疯狂断充 30 | STEP_CHARGING_DISABLED_THRESHOLD=15 31 | 32 | #以下两个配置添加电量控制时生效 33 | #停止充电的电量阈值(电量大于等于此值时停止充电) 34 | CHARGE_STOP=95 35 | #开始充电的电量阈值(电量小于等于此值时开始充电) 36 | CHARGE_START=80 37 | 38 | #以下三个配置添加温控时生效 39 | #降低充电电流的温度阈值(单位:℃) 40 | TEMP_MAX=52 41 | #当高于温度阈值时的最大充电电流(单位:μA) 42 | HIGHEST_TEMP_CURRENT=2000000 43 | #恢复快充的温度阈值(单位:℃) 44 | RECHARGE_TEMP=45 45 | 46 | #是否启用“伪”旁路供电功能(1为启用,其他数字为禁用) 47 | #使用多线程+popen执行Shell命令来获取前台应用,所以开启后会消耗更多的系统资源 48 | #为尽量减少系统资源的消耗,每5秒获取一次前台应用包名,不可更改 49 | #未经完全测试,如果日志没有提示该功能失效且开启后无效,请及时前往Github进行反馈 50 | #开启后请配置/data/adb/turbo-charge/bypass_charge.txt文件 51 | BYPASS_CHARGE=0 52 | -------------------------------------------------------------------------------- /module/common/service.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | MODDIR=${0%/*} 3 | [[ -f /data/adb/turbo-charge/log.txt ]] && mv -f /data/adb/turbo-charge/log.txt /data/adb/turbo-charge/log.txt.old 4 | echo "等待手机启动完毕,以确保时间准确。若只看到这一行内容,请立即联系模块作者!" > /data/adb/turbo-charge/log.txt 5 | until [[ "$(getprop service.bootanim.exit)" == "1" ]]; do 6 | sleep 1 7 | done 8 | echo "手机启动完毕" >> /data/adb/turbo-charge/log.txt 9 | echo "" >> /data/adb/turbo-charge/log.txt 10 | [[ -e /data/vendor/thermal ]] && chattr -i $(find /data/vendor/thermal) 11 | rm -rf /data/vendor/thermal 12 | mkdir -p /data/vendor/thermal/config 13 | chattr +i /data/vendor/thermal/config /data/vendor/thermal 14 | nohup ${MODDIR}/turbo-charge > /dev/null 2>&1 & 15 | sleep 1 16 | first_process=$(ps -eo comm,pid | grep "turbo-charge" | awk '{print $2}') 17 | nohup ${MODDIR}/turbo-charge >> /data/adb/turbo-charge/log.txt 2>&1 & 18 | sleep 60 19 | [[ -n "${first_process}" ]] && kill ${first_process} 20 | -------------------------------------------------------------------------------- /module/common/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/system/bin/sh 2 | [[ -e /data/vendor/thermal ]] && chattr -i $(find /data/vendor/thermal) 3 | rm -rf /data/vendor/thermal /data/adb/turbo-charge 4 | mkdir -p /data/vendor/thermal/config 5 | -------------------------------------------------------------------------------- /module/customize.sh: -------------------------------------------------------------------------------- 1 | SKIPUNZIP=1 2 | 3 | check_file() 4 | { 5 | ui_print " --- 检查所需文件是否存在 ---" 6 | temp_file=$(ls /sys/class/power_supply/*/temp 2>/dev/null) 7 | current_max_file=$(ls /sys/class/power_supply/*/constant_charge_current_max /sys/class/power_supply/*/fast_charge_current /sys/class/power_supply/*/thermal_input_current 2>/dev/null) 8 | for i in $(ls /sys/class/thermal | grep "thermal_zone"); do 9 | if [[ -f "/sys/class/thermal/${i}/type" ]]; then 10 | temp_sensor=$(cat /sys/class/thermal/${i}/type 2>/dev/null) 11 | for j in lcd_therm quiet_therm conn_therm modem_therm wifi_therm mtktsbtsnrpa mtktsbtsmdpa mtktsAP modem-0-usr modem1_wifi ddr-usr cwlan-usr; do 12 | [[ "${temp_sensor}" == "${j}" ]] && have_temp_sensor=1 && break 13 | done 14 | fi 15 | [[ -n "${have_temp_sensor}" ]] && break 16 | done 17 | if [[ ! -f "/sys/class/power_supply/battery/status" ]]; then 18 | no_battery_status=1 19 | fi 20 | if [[ ! -f "/sys/class/power_supply/battery/capacity" ]]; then 21 | no_battery_capacity=1 22 | fi 23 | if [[ ! -f "/sys/class/power_supply/battery/charging_enabled" && ! -f "/sys/class/power_supply/battery/battery_charging_enabled" && ! -f "/sys/class/power_supply/battery/input_suspend" && ! -f "/sys/class/qcom-battery/restricted_charging" ]]; then 24 | no_suspend_file=1 25 | fi 26 | if [[ -n "${no_battery_status}" ]]; then 27 | ui_print " !由于找不到有关文件,“伪”旁路供电功能无法根据手机的充电状态而自动启停,详情请看程序运行时的log文件!" 28 | fi 29 | if [[ -n "${no_battery_status}" || -n "${no_battery_capacity}" || -n "${no_suspend_file}" ]]; then 30 | ui_print " !由于找不到有关文件,电量控制功能失效,详情请看程序运行时的log文件!" 31 | no_power_control=1 32 | fi 33 | if [[ ! -f "/sys/class/power_supply/battery/step_charging_enabled" ]]; then 34 | ui_print " !由于找不到有关文件,阶梯充电控制的所有功能失效,详情请看程序运行时的log文件!" 35 | no_step_charging=1 36 | elif [[ -n "${no_battery_capacity}" ]]; then 37 | ui_print " !由于找不到部分有关文件,阶梯式充电控制的部分功能失效,详情请看程序运行时的log文件!" 38 | fi 39 | if [[ -z "${current_max_file}" ]]; then 40 | ui_print " !由于找不到有关文件,有关电流的所有功能(包括“伪”旁路供电功能)失效,详情请看程序运行时的log文件!" 41 | no_current_change=1 42 | fi 43 | if [[ -z "${temp_file}" || -n "${no_battery_status}" ]]; then 44 | ui_print " !由于找不到有关文件,充电时强制显示28℃功能失效,详情请看程序运行时的log文件!" 45 | no_force_temp=1 46 | fi 47 | if [[ -z "${no_force_temp}" || -z "${no_current_change}" ]]; then 48 | if [[ -z "${have_temp_sensor}" ]]; then 49 | if [[ -n "${no_force_temp}" ]]; then 50 | ui_print " !由于找不到有关温度传感器,温度控制功能失效,详情请看程序运行时的log文件!" 51 | else 52 | ui_print " !由于找不到有关温度传感器,温度控制及充电时强制显示28℃功能失效,详情请看程序运行时的log文件!" 53 | no_force_temp=1 54 | fi 55 | fi 56 | [[ -n "${no_step_charging}" && -n "${no_power_control}" && -n "${no_force_temp}" && -n "${no_current_change}" && -z "${have_temp_sensor}" ]] && force_exit=1 57 | else 58 | [[ -n "${no_step_charging}" && -n "${no_power_control}" && -n "${no_force_temp}" && -n "${no_current_change}" ]] && force_exit=1 59 | fi 60 | if [[ -n "${force_exit}" ]]; then 61 | ui_print " !所有的所需文件均不存在,完全不适配此手机,安装失败!" 62 | ui_print " " 63 | rm -rf ${MODPATH} 64 | exit 1 65 | fi 66 | ui_print " - 检查完毕,开始安装" 67 | } 68 | 69 | print_modname() 70 | { 71 | ui_print " " 72 | ui_print " ********************************************************" 73 | ui_print " " 74 | ui_print " - 模块: $(grep '^name=' ${TMPDIR}/module.prop | sed 's/^name=//g')" 75 | ui_print " - 模块版本: $(grep '^version=' ${TMPDIR}/module.prop | sed 's/^version=//g')" 76 | ui_print " - 作者: $(grep '^author=' ${TMPDIR}/module.prop | sed 's/^author=//g')" 77 | ui_print " " 78 | ui_print " ********************************************************" 79 | ui_print " " 80 | } 81 | 82 | print_info() 83 | { 84 | ui_print " " 85 | ui_print " ********************************************************" 86 | ui_print " " 87 | ui_print " - 可修改/data/adb/turbo-charge/option.txt来更改一些参数,即时生效" 88 | ui_print " - log文件为同目录的log.txt,包含文件检测、配置更改等信息" 89 | ui_print " " 90 | ui_print " ********************************************************" 91 | ui_print " " 92 | ui_print " !!!如果安装模块后卡开机,请删除模块目录下的system文件夹!!!" 93 | ui_print " " 94 | ui_print " !!!卸载模块请务必在Magisk中卸载!!!" 95 | ui_print " !!!或手动执行模块目录下的uninstall.sh文件后再删除模块目录!!!" 96 | ui_print " " 97 | ui_print " ********************************************************" 98 | ui_print " " 99 | ui_print " - ↓模块介绍↓" 100 | ui_print " - 删除温控,充电时持续修改电池温度,让系统认为电池温度一直是28℃" 101 | ui_print " - 持续修改充电电流,以达到最快充电速度" 102 | ui_print " - 可选添加温控,若添加,默认当手机温度高于52℃时最高充电电流限制为2A" 103 | ui_print " - 可选添加电量控制,若添加,默认电量到达95%时断电,小于等于80%时恢复充电" 104 | ui_print " - 可选是否关闭阶梯式充电,若选是,默认电量大于15%时关闭阶梯式充电,电量小于等于15%时开启阶梯式充电" 105 | ui_print " - 可选是否启用“伪”旁路充电,但请注意是“伪”,因为并不是真的旁路供电,而是直接将充电电流降低至500mA" 106 | ui_print " " 107 | ui_print " !!!若手机体感温度过高,请立即拔下充电器并将手机静置在阴凉处!!!" 108 | ui_print " " 109 | ui_print " ********************************************************" 110 | ui_print " " 111 | } 112 | 113 | check_old_option() 114 | { 115 | for i in $(seq $#); do 116 | VARIABLE=$(eval echo '${'"${i}"'}') 117 | VALUE=$(grep "^${VARIABLE}=" /data/adb/turbo-charge/option.txt | sed "s/^${VARIABLE}=//g") 118 | VALUE_DEFAULT=$(grep "^${VARIABLE}=" ${TMPDIR}/option.txt | sed "s/^${VARIABLE}=//g") 119 | if [[ -z "${VALUE}" ]]; then 120 | ui_print " - ${VARIABLE}不存在,使用默认值${VALUE_DEFAULT}" 121 | elif [[ -z "$(echo "${VALUE}" | grep '^[[:digit:]]*$')" ]]; then 122 | ui_print " - ${VARIABLE}的值为空或非纯数字(正整数),使用默认值${VALUE_DEFAULT}" 123 | elif [[ "${VALUE}" -gt 2147483647 ]]; then 124 | ui_print " - ${VARIABLE}的值大于2147483647,这是不被允许的,使用默认值${VALUE_DEFAULT}" 125 | elif [[ "${VALUE}" -eq 0 && "${VARIABLE}" == "CYCLE_TIME" ]]; then 126 | ui_print " - ${VARIABLE}的值等于0,这是不被允许的,使用默认值${VALUE_DEFAULT}" 127 | else 128 | ui_print " - ${VARIABLE}的值为${VALUE},将此值写入新配置文件" 129 | sed -i "s/^${VARIABLE}=.*/${VARIABLE}=${VALUE}/g" ${TMPDIR}/option.txt 130 | fi 131 | done 132 | } 133 | 134 | on_install() 135 | { 136 | if [[ -f /data/adb/turbo-charge/option.txt ]]; then 137 | ui_print " 旧配置文件存在,开始读取旧配置文件的配置" 138 | check_old_option CYCLE_TIME FORCE_TEMP CURRENT_MAX STEP_CHARGING_DISABLED 139 | check_old_option TEMP_CTRL POWER_CTRL STEP_CHARGING_DISABLED_THRESHOLD 140 | check_old_option CHARGE_STOP CHARGE_START TEMP_MAX HIGHEST_TEMP_CURRENT 141 | check_old_option RECHARGE_TEMP BYPASS_CHARGE 142 | else 143 | ui_print " 旧配置文件不存在,使用默认配置" 144 | ui_print " - 添加温控,当温度高于52℃时限制最高充电电流为2A,低于45℃时恢复" 145 | ui_print " - 不添加电量控制" 146 | ui_print " - 不关闭阶梯式充电" 147 | ui_print " - 启用强制显示28℃功能" 148 | ui_print " - 禁用“伪”旁路供电功能" 149 | fi 150 | ui_print " " 151 | ui_print " ********************************************************" 152 | ui_print " " 153 | [[ -f /data/adb/turbo-charge/bypass_charge.txt ]] && BYPASS_APP=$(grep -v -E "#|^$" /data/adb/turbo-charge/bypass_charge.txt) 154 | if [[ -n "${BYPASS_APP}" ]]; then 155 | echo " 以下APP包名位于旧的“伪”旁路供电列表中,将会写入到新的“伪”旁路供电列表" 156 | for s in ${BYPASS_APP}; do 157 | ui_print " - ${s}" 158 | echo "${s}" >> ${TMPDIR}/bypass_charge.txt 159 | done 160 | ui_print " " 161 | ui_print " ********************************************************" 162 | ui_print " " 163 | fi 164 | cp -af ${TMPDIR}/turbo-charge ${TMPDIR}/module.prop ${TMPDIR}/service.sh ${TMPDIR}/uninstall.sh ${MODPATH} 165 | [[ ! -d /data/adb/turbo-charge ]] && mkdir -p /data/adb/turbo-charge 166 | cp -af ${TMPDIR}/option.txt ${TMPDIR}/bypass_charge.txt /data/adb/turbo-charge 167 | for k in /system/bin /system/etc/init /system/etc/perf /system/vendor/bin /system/vendor/etc /system/vendor/etc/init /system/vendor/etc/perf; do 168 | all_thermal="${all_thermal} $(find ${k} -maxdepth 1 -type f -name '*thermal*' 2>/dev/null)" 169 | done 170 | all_thermal="${all_thermal} $(find /system/vendor/etc -maxdepth 1 -type f -name 'powerhint*' 2>/dev/null)" 171 | all_thermal="${all_thermal} $(find /system/vendor/lib/hw -maxdepth 1 -type f -name 'thermal*' 2>/dev/null)" 172 | all_thermal="${all_thermal} $(find /system/vendor/lib64/hw -maxdepth 1 -type f -name 'thermal*' 2>/dev/null)" 173 | for thermal in ${all_thermal}; do 174 | mkdir -p ${MODPATH}${thermal%/*} 175 | touch ${MODPATH}${thermal} 176 | done 177 | [[ -e /data/vendor/thermal ]] && chattr -i $(find /data/vendor/thermal) 178 | rm -rf /data/vendor/thermal 179 | mkdir -p /data/vendor/thermal/config 180 | chattr +i /data/vendor/thermal/config /data/vendor/thermal 181 | } 182 | 183 | set_permissions() 184 | { 185 | set_perm_recursive ${MODPATH} 0 0 0755 0777 186 | set_perm_recursive /data/adb/turbo-charge 0 0 0755 0777 187 | } 188 | 189 | unzip -oj "${ZIPFILE}" module.prop 'common/*' -d ${TMPDIR} >&2 190 | print_modname 191 | check_file 192 | print_info 193 | on_install 194 | set_permissions 195 | -------------------------------------------------------------------------------- /module/module.prop: -------------------------------------------------------------------------------- 1 | id=turbo-charge 2 | name=充电加速 3 | version=v68 4 | versionCode=68 5 | author=酷安@诺鸡鸭 6 | description=删除温控,关闭阶梯式充电,持续修改电池温度及充电电流,尽可能的让手机满血快充。配置文件在/data/adb/turbo-charge/option.txt,可以更改一些参数,日志文件为同目录的log.txt 7 | updateJson=https://gitee.com/chase535/turbo-charge/raw/main/update_channel/turbo-charge.json 8 | -------------------------------------------------------------------------------- /src/foreground_app.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "printf_with_time.h" 10 | #include "options_linkedlist.h" 11 | #include "foreground_app.h" 12 | 13 | //全局变量,用于存储当前前台应用的包名 14 | volatile char ForegroundAppName[100]={0}; 15 | 16 | /* 17 | 获取前台应用的包名以配合“伪”旁路供电功能使用 18 | 我是干嵌入式系统开发的,对AndroidNDK不熟悉,无法使用纯C语言实现,所以只能使用popen管道执行Shell命令来获取 19 | 但这就导致了执行效率的大幅下降,我无能为力,只能等待其他大佬的PR 20 | */ 21 | void *get_foreground_appname(void *android_version) 22 | { 23 | while(read_one_option("BYPASS_CHARGE") == 1) 24 | { 25 | //在循环体内定义变量,这样变量仅存在于单次循环,每次循环结束后变量自动释放,循环开始时变量重新定义 26 | char result[APP_PACKAGE_NAME_MAX_SIZE+100]={0},*tmpchar1,*tmpchar2; 27 | FILE *fp; 28 | //判断是否为锁屏状态,如果是则无法获取应用包名,直接将全局变量ForegroundAppName赋值为screen_is_off 29 | fp=popen("dumpsys deviceidle | grep 'mScreenOn'", "r"); 30 | if(fp == NULL) 31 | { 32 | printf_with_time("无法创建管道通信,跳过本次循环!"); 33 | continue_no_print: 34 | sleep(5); 35 | //添加进程取消点,否则无法通过调用pthread_exit()函数取消进程 36 | //下面所有pthread_testcancel()函数的作用都同上 37 | pthread_testcancel(); 38 | continue; 39 | } 40 | fgets(result, sizeof(result), fp); 41 | pclose(fp); 42 | fp=NULL; 43 | line_feed(result); 44 | //此Shell命令的返回值格式为 mScreenOn=true 45 | //若为true则没有锁屏,若为false则处于锁屏状态 46 | tmpchar1=strstr(result, "="); 47 | if(tmpchar1 == NULL) 48 | { 49 | printf_with_time("无法获取锁屏状态,跳过本次循环!"); 50 | goto continue_no_print; 51 | } 52 | if(strcmp(tmpchar1+1, "true")) 53 | { 54 | pthread_mutex_lock((pthread_mutex_t *)&mutex_foreground_app); 55 | strncpy((char *)ForegroundAppName, "screen_is_off", APP_PACKAGE_NAME_MAX_SIZE-1); 56 | pthread_mutex_unlock((pthread_mutex_t *)&mutex_foreground_app); 57 | goto continue_no_print; 58 | } 59 | /* 60 | 如果非锁屏状态,则获取前台应用包名 61 | 安卓10及以上可使用dumpsys activity lru获取应用状态 62 | 安卓10以下就只能用dumpsys activity o获取,执行效率慢 63 | 然后再使用grep提取出包含关键字的行,此行即为前台应用的详情 64 | */ 65 | fp=(*((int *)android_version) < 10)?popen("dumpsys activity o | grep ' (top-activity)'", "r"):popen("dumpsys activity lru | grep ' TOP'", "r"); 66 | if(fp == NULL) 67 | { 68 | printf_with_time("无法创建管道通信,跳过本次循环!"); 69 | goto continue_no_print; 70 | } 71 | fgets(result, sizeof(result), fp); 72 | pclose(fp); 73 | fp=NULL; 74 | line_feed(result); 75 | tmpchar1=(*((int *)android_version) < 10)?strstr(result, "/TOP"):strstr(result, " TOP"); 76 | if(tmpchar1 == NULL) 77 | { 78 | can_not_get_package: 79 | printf_with_time("无法获取前台应用包名,跳过本次循环!"); 80 | goto continue_no_print; 81 | } 82 | /* 83 | 从上一步获取到的前台应用的详情中截取应用包名 84 | dumpsys activity lru获取到的详情格式为 #98: fg TOP LCMN 4493:com.termux/u0a351 act:activities|recents 85 | dumpsys activity o获取到的详情格式为 Proc # 0: fg T/A/TOP LCMN t: 0 4493:com.termux/u0a351 (top-activity) 86 | */ 87 | tmpchar2=(*((int *)android_version) < 10)?strstr(strstr(tmpchar1, ":")+1, ":"):strstr(tmpchar1, ":"); 88 | if(tmpchar2 == NULL) goto can_not_get_package; 89 | tmpchar1=strstr(tmpchar2, "/"); 90 | if(tmpchar1 == NULL) goto can_not_get_package; 91 | *tmpchar1='\0'; 92 | pthread_testcancel(); 93 | //将前台应用包名赋值给ForegroundAppName 94 | pthread_mutex_lock((pthread_mutex_t *)&mutex_foreground_app); 95 | strncpy((char *)ForegroundAppName, tmpchar2+1, APP_PACKAGE_NAME_MAX_SIZE-1); 96 | pthread_mutex_unlock((pthread_mutex_t *)&mutex_foreground_app); 97 | sleep(5); 98 | pthread_testcancel(); 99 | } 100 | //如果配置文件的BYPASS_CHARGE值不为1,则退出循环并将ForegroundAppName清空 101 | pthread_mutex_lock((pthread_mutex_t *)&mutex_foreground_app); 102 | memset((void *)ForegroundAppName, 0, sizeof(ForegroundAppName)); 103 | pthread_mutex_unlock((pthread_mutex_t *)&mutex_foreground_app); 104 | return NULL; 105 | } 106 | 107 | //获取安卓版本,因为只有安卓7及以上才能使用Shell命令获取安卓版本 108 | int check_android_version() 109 | { 110 | char android_version_char[5]; 111 | int android_version=0; 112 | FILE *fp=NULL; 113 | fp=popen("getprop ro.build.version.release", "r"); 114 | if(fp == NULL) 115 | { 116 | printf_with_time("无法创建管道通信,故无法获取安卓版本,“伪”旁路供电功能失效!"); 117 | return 0; 118 | } 119 | fgets(android_version_char, sizeof(android_version_char), fp); 120 | line_feed(android_version_char); 121 | pclose(fp); 122 | fp=NULL; 123 | if(!strlen(android_version_char)) 124 | { 125 | printf_with_time("无法获取安卓版本,而只有安卓7及以上能够通过Shell命令获取前台应用,所以必须要获取安卓版本进行判断,“伪”旁路供电功能失效!"); 126 | return 0; 127 | } 128 | android_version=atoi(android_version_char); 129 | if(android_version < 7) 130 | { 131 | printf_with_time("安卓7及以下无法通过Shell命令获取前台应用,当前版本为安卓%d,“伪”旁路供电功能失效!", android_version); 132 | return 0; 133 | } 134 | return android_version; 135 | } 136 | -------------------------------------------------------------------------------- /src/global.c: -------------------------------------------------------------------------------- 1 | #include "global.h" 2 | 3 | /* 4 | 一些随时都可能修改的变量,单独拿出来以便于后续修改 5 | 在global.h头文件中还有一个关于旁路充电电流的宏定义 6 | */ 7 | 8 | char option_file[]="/data/adb/turbo-charge/option.txt"; 9 | char bypass_charge_file[]="/data/adb/turbo-charge/bypass_charge.txt"; 10 | char temp_sensors[][15]={"conn_therm", "modem_therm", "wifi_therm", "mtktsbtsnrpa", "lcd_therm", "quiet_therm", 11 | "mtktsbtsmdpa", "mtktsAP", "modem-0-usr", "modem1_wifi", "ddr-usr", "cwlan-usr"}; 12 | char temp_sensor_quantity=sizeof(temp_sensors)/sizeof(temp_sensors[0]); 13 | -------------------------------------------------------------------------------- /src/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "main.h" 11 | #include "read_option_file.h" 12 | #include "options_linkedlist.h" 13 | #include "some_ctrl.h" 14 | #include "my_malloc.h" 15 | #include "printf_with_time.h" 16 | #include "value_set.h" 17 | #include "foreground_app.h" 18 | 19 | /* 20 | 列出path目录下的所有文件夹并赋值给二级指针变量ppp 21 | 第二个参数是二级指针的地址 22 | 返回值是文件夹的个数 23 | */ 24 | int list_dir(char *path, char ***ppp) 25 | { 26 | DIR *pDir; 27 | struct dirent *ent; 28 | int file_num=0; 29 | pDir=opendir(path); 30 | if(pDir != NULL) 31 | { 32 | //重新分配一个足够大的内存,用来记录文件夹的个数 33 | *ppp=(char **)my_realloc(*ppp, sizeof(char *)*500); 34 | while((ent=readdir(pDir)) != NULL) 35 | { 36 | if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) continue; 37 | //分配一个与路径字符串大小相等的内存,用来装路径 38 | (*ppp)[file_num]=(char *)my_calloc(1, sizeof(char)*((strlen(path)+strlen(ent->d_name))+2)); 39 | //拼接路径及文件夹名 40 | sprintf((*ppp)[file_num], "%s/%s", path, ent->d_name); 41 | file_num++; 42 | } 43 | closedir(pDir); 44 | //收缩内存 45 | *ppp=(char **)my_realloc(*ppp, sizeof(char *)*file_num); 46 | } 47 | return file_num; 48 | } 49 | 50 | //将字符串中的回车符、换行符换为字符串结束符 51 | void line_feed(char *line) 52 | { 53 | char *p; 54 | p=strchr(line, '\r'); 55 | if(p != NULL) *p='\0'; 56 | p=strchr(line, '\n'); 57 | if(p != NULL) *p='\0'; 58 | } 59 | 60 | /* 61 | 检查文件是否可读 62 | 若文件存在且不可读,延时0.25秒后重新检查 63 | 检查两次是为了兼容在本程序检查时刚好被系统的其他进程锁住(如刚好进行了文件的保存操作)导致的无法读取 64 | 若仍不可读尝试修改权限后重新检查是否可读 65 | 若文件不存在或修改权限后仍不可读,则强制停止程序运行 66 | */ 67 | void check_read_file(char *file) 68 | { 69 | if(!access(file, F_OK)) 70 | { 71 | check_permission: 72 | if(access(file, R_OK)) 73 | { 74 | //权限0644不得简写成644 75 | chmod(file, 0644); 76 | if(!access(file, R_OK)) return; 77 | printf_with_time("无法读取%s文件,程序强制退出!", file); 78 | exit(1); 79 | } 80 | } 81 | else 82 | { 83 | struct timespec req={0, 250000000L}; 84 | nanosleep(&req, NULL); 85 | if(!access(file, F_OK)) goto check_permission; 86 | else 87 | { 88 | printf_with_time("找不到%s文件,程序强制退出!", file); 89 | exit(999); 90 | } 91 | } 92 | } 93 | 94 | //读取文件内容,若文件不存在则程序强制退出 95 | void read_file(char *file_path, char *char_var, int max_char_num) 96 | { 97 | FILE *fp; 98 | check_read_file(file_path); 99 | fp=fopen(file_path, "rt"); 100 | fgets(char_var, max_char_num, fp); 101 | fclose(fp); 102 | fp=NULL; 103 | line_feed(char_var); 104 | } 105 | 106 | //查找可用温度传感器 107 | int find_temp_sensor(char *temp_sensor) 108 | { 109 | FILE *fq; 110 | struct stat statbuf; 111 | char *temp_sensor_dir = NULL, *buffer = NULL, *temp_tmp = NULL, *msg = NULL; 112 | char **thermal_dir = NULL; 113 | int thermal_file_num = 0, i = 0, j = 0, temp_sensor_num = 100; 114 | 115 | //预先分配一个占位用的内存 116 | temp_sensor=(char *)my_calloc(1, sizeof(char)); 117 | temp_sensor_dir=(char *)my_calloc(1, sizeof(char)); 118 | buffer=(char *)my_calloc(1, sizeof(char)); 119 | temp_tmp=(char *)my_calloc(1, sizeof(char)*15); 120 | msg=(char *)my_calloc(1, sizeof(char)); 121 | thermal_dir=(char **)my_calloc(1, sizeof(char *)); 122 | thermal_file_num=list_dir("/sys/class/thermal", &thermal_dir); 123 | //遍历/sys/class/thermal 124 | for(i=0;i < thermal_file_num;i++) 125 | { 126 | //判断/sys/class/thermal下各个文件夹的名是否包含thermal_zone 127 | //因为温度传感器的相关文件就在此类文件夹中 128 | if(strstr(thermal_dir[i], "thermal_zone") != NULL) 129 | { 130 | //判断该文件夹内是否有一个名为type的文件,此文件的内容为该温度传感器的名称 131 | buffer=(char *)my_realloc(buffer, sizeof(char)*(strlen(thermal_dir[i])+6)); 132 | sprintf(buffer, "%s/type", thermal_dir[i]); 133 | //如果没有type文件或type文件不可读,则跳过此温度传感器的后续操作 134 | if(access(buffer, R_OK)) continue; 135 | //获取type文件内的字符个数 136 | stat(buffer, &statbuf); 137 | fq=fopen(buffer, "rt"); 138 | if(fq == NULL) continue; 139 | //重新分配内存,使其刚好能够装入该温度传感器的名称,并获取该温度传感器的名称 140 | msg=(char *)my_realloc(msg, sizeof(char)*(statbuf.st_size+1)); 141 | fgets(msg, statbuf.st_size+1, fq); 142 | fclose(fq); 143 | fq=NULL; 144 | //如果无法通过管道打开type文件,则跳过此温度传感器的后续操作 145 | line_feed(msg); 146 | //检查此文件夹下有无temp文件,此文件的内容是该温度传感器所获取的温度值 147 | sprintf(buffer, "%s/temp", thermal_dir[i]); 148 | //如果没有temp文件或temp文件不可读,则跳过此温度传感器的后续操作 149 | if(access(buffer, R_OK)) continue; 150 | fq=fopen(buffer, "rt"); 151 | if(fq != NULL) 152 | { 153 | fgets(temp_tmp, 10, fq); 154 | fclose(fq); 155 | fq=NULL; 156 | } 157 | //如果无法通过管道打开temp文件,则跳过此温度传感器的后续操作 158 | else continue; 159 | line_feed(temp_tmp); 160 | //判断temp文件的值是否正常,若不正常则代表不能使用此温度传感器,跳过此温度传感器的后续操作 161 | if(atoi(temp_tmp) == 1 || atoi(temp_tmp) == 0 || atoi(temp_tmp) == -1) continue; 162 | //根据温度传感器的优先级顺序进行筛选,最终选择优先级最高的可用的温度传感器 163 | for(j=0;j < temp_sensor_quantity;j++) 164 | { 165 | if(!strcmp(msg, temp_sensors[j]) && temp_sensor_num > j) 166 | { 167 | temp_sensor_num=j; 168 | //重新分配内存保证了最小内存使用量,temp_sensor_dir只是温度传感器的所在路径,后续会进行拼接 169 | temp_sensor_dir=(char *)my_realloc(temp_sensor_dir, sizeof(char)*(strlen(thermal_dir[i])+1)); 170 | strcpy(temp_sensor_dir, thermal_dir[i]); 171 | } 172 | } 173 | } 174 | } 175 | my_free(buffer); 176 | buffer=NULL; 177 | my_free(temp_tmp); 178 | temp_tmp=NULL; 179 | my_free(msg); 180 | msg=NULL; 181 | free_malloc_memory(&thermal_dir, thermal_file_num); 182 | //判断是否获取到了可用的温度传感器 183 | if(temp_sensor_num != 100) 184 | { 185 | //重新分配内存,使其刚好能够装下路径+“/temp”,因为temp文件内存储的是温度传感器所获取的温度值 186 | temp_sensor=(char *)my_realloc(temp_sensor, sizeof(char)*(strlen(temp_sensor_dir)+6)); 187 | sprintf(temp_sensor, "%s/temp", temp_sensor_dir); 188 | printf_with_time("将使用%s温度传感器作为手机温度的获取源。由于每个传感器所处位置不同以及每个手机发热区不同,很可能导致获取到的温度与实际体感温度不同", temp_sensors[temp_sensor_num]); 189 | check_read_file(temp_sensor); 190 | my_free(temp_sensor_dir); 191 | temp_sensor_dir=NULL; 192 | return 1; 193 | } 194 | //如果没有获取到可用的温度传感器,则返回0 195 | else 196 | { 197 | my_free(temp_sensor_dir); 198 | temp_sensor_dir=NULL; 199 | my_free(temp_sensor); 200 | temp_sensor=NULL; 201 | return 0; 202 | } 203 | } 204 | 205 | int main() 206 | { 207 | char *temp_sensor = NULL,**current_limit_file = NULL,**power_supply_dir_list = NULL,**power_supply_dir = NULL,**current_max_file = NULL,**temp_file = NULL; 208 | char charge[25]={0},power[10]={0},current_max_char[20]={0},highest_temp_current_char[20]={0},thermal[15]={0},last_appname[APP_PACKAGE_NAME_MAX_SIZE]={0}; 209 | uchar step_charge=1,power_control=1,force_temp=1,has_force_temp=0,current_change=1,battery_status=1,battery_capacity=1; 210 | int i=0,j=0,temp_int=0,power_supply_file_num=0,current_limit_file_num=0,last_charge_stop=-1,charge_is_stop=0,is_first_time=1,temp_sensor_num=0; 211 | int power_supply_dir_list_num=0,current_max_file_num=0,temp_file_num=0,is_bypass=0,can_get_foreground=0,screen_is_off=0,last_temp_max=-1,last_charge_status=0,read_option_time=5; 212 | regex_t temp_re = {0},current_max_re = {0},current_limit_re = {0}; 213 | regmatch_t temp_pmatch = {0},current_max_pmatch = {0},current_limit_pmatch = {0}; 214 | pthread_t thread1 = {0},thread2 = {0}; 215 | //初始化链表 216 | insert_all_option(); 217 | printf("作者:酷安@诺鸡鸭\n"); 218 | printf("GitHub开源地址:https://github.com/chase535/turbo-charge\n\n"); 219 | //如果是写入文件,则必须加上这句话,不然只能等缓冲区满了后才会一次性写入 220 | fflush(stdout); 221 | //判断各个所需文件是否存在 222 | if(access("/sys/class/power_supply/battery/status", F_OK)) battery_status=0; 223 | if(access("/sys/class/power_supply/battery/capacity", F_OK)) battery_capacity=0; 224 | if(!battery_status || !battery_capacity) 225 | { 226 | power_control=0; 227 | if(battery_status && !battery_capacity) printf_with_time("由于找不到/sys/class/power_supply/battery/capacity文件,电量控制功能失效!"); 228 | else if(!battery_status && battery_capacity) printf_with_time("由于找不到/sys/class/power_supply/battery/status文件,电量控制功能失效,且“伪”旁路供电功能无法根据手机的充电状态而自动启停!"); 229 | else printf_with_time("由于找不到/sys/class/power_supply/battery/status和/sys/class/power_supply/battery/capacity文件,电量控制功能失效,且“伪”旁路供电功能无法根据手机的充电状态而自动启停!"); 230 | } 231 | else if(access("/sys/class/power_supply/battery/charging_enabled", F_OK) && access("/sys/class/power_supply/battery/battery_charging_enabled", F_OK) && access("/sys/class/power_supply/battery/input_suspend", F_OK) && access("/sys/class/qcom-battery/restricted_charging", F_OK)) 232 | { 233 | power_control=0; 234 | printf_with_time("由于找不到控制手机暂停充电的文件,电量控制功能失效!"); 235 | printf_with_time("目前已知的有关文件有:/sys/class/power_supply/battery/charging_enabled、/sys/class/power_supply/battery/battery_charging_enabled、/sys/class/power_supply/battery/input_suspend、/sys/class/qcom-battery/restricted_charging"); 236 | printf_with_time("如果您知道其他的有关文件,请联系模块制作者!"); 237 | } 238 | if(access("/sys/class/power_supply/battery/step_charging_enabled", F_OK)) 239 | { 240 | step_charge=0; 241 | printf_with_time("由于找不到/sys/class/power_supply/battery/step_charging_enabled文件,阶梯式充电控制的所有功能失效!"); 242 | } 243 | else if(!battery_capacity) 244 | { 245 | step_charge=2; 246 | printf_with_time("由于找不到/sys/class/power_supply/battery/capacity文件,阶梯式充电无法根据电量进行开关,此时若在配置中关闭阶梯式充电,则无论电量多少,阶梯式充电都会关闭!"); 247 | } 248 | //使用正则表达式,用来模糊查找相应文件 249 | regcomp(¤t_max_re, ".*/constant_charge_current_max$|.*/fast_charge_current$|.*/thermal_input_current$", REG_EXTENDED|REG_NOSUB); 250 | regcomp(¤t_limit_re, ".*/thermal_input_current_limit$", REG_EXTENDED|REG_NOSUB); 251 | regcomp(&temp_re, ".*/temp$", REG_EXTENDED|REG_NOSUB); 252 | power_supply_dir=(char **)my_calloc(1, sizeof(char *)); 253 | power_supply_file_num=list_dir("/sys/class/power_supply", &power_supply_dir); 254 | //预先分配一个足够大的内存,用来记录文件的个数 255 | current_limit_file=(char **)my_calloc(1, sizeof(char *)*100); 256 | current_max_file=(char **)my_calloc(1, sizeof(char *)*100); 257 | temp_file=(char **)my_calloc(1, sizeof(char *)*100); 258 | //遍历/sys/class/power_supply 259 | for(i=0;i < power_supply_file_num;i++) 260 | { 261 | power_supply_dir_list=(char **)my_calloc(1, sizeof(char *)); 262 | power_supply_dir_list_num=list_dir(power_supply_dir[i], &power_supply_dir_list); 263 | //遍历/sys/class/power_supply路径下的所有文件夹 264 | for(j=0;j < power_supply_dir_list_num;j++) 265 | { 266 | //如果匹配到了文件,则分配一个与路径字符串大小相等的内存,装入路径,并且记录相应文件数量的变量值+1 267 | if(!regexec(¤t_max_re, power_supply_dir_list[j], 1, ¤t_max_pmatch, 0)) 268 | { 269 | current_max_file[current_max_file_num]=(char *)my_calloc(1, sizeof(char)*(strlen(power_supply_dir_list[j])+1)); 270 | strcpy(current_max_file[current_max_file_num], power_supply_dir_list[j]); 271 | current_max_file_num++; 272 | } 273 | else if(!regexec(¤t_limit_re, power_supply_dir_list[j], 1, ¤t_limit_pmatch, 0)) 274 | { 275 | current_limit_file[current_limit_file_num]=(char *)my_calloc(1, sizeof(char)*(strlen(power_supply_dir_list[j])+1)); 276 | strcpy(current_limit_file[current_limit_file_num], power_supply_dir_list[j]); 277 | current_limit_file_num++; 278 | } 279 | else if(!regexec(&temp_re, power_supply_dir_list[j], 1, &temp_pmatch, 0)) 280 | { 281 | temp_file[temp_file_num]=(char *)my_calloc(1, sizeof(char)*(strlen(power_supply_dir_list[j])+1)); 282 | strcpy(temp_file[temp_file_num], power_supply_dir_list[j]); 283 | temp_file_num++; 284 | } 285 | } 286 | free_malloc_memory(&power_supply_dir_list, power_supply_dir_list_num); 287 | } 288 | regfree(¤t_max_re); 289 | regfree(¤t_limit_re); 290 | regfree(&temp_re); 291 | free_malloc_memory(&power_supply_dir, power_supply_file_num); 292 | //收缩内存 293 | current_limit_file=(char **)my_realloc(current_limit_file, sizeof(char *)*current_limit_file_num); 294 | current_max_file=(char **)my_realloc(current_max_file, sizeof(char *)*current_max_file_num); 295 | temp_file=(char **)my_realloc(temp_file, sizeof(char *)*temp_file_num); 296 | //判断文件数量是否为0 297 | if(!current_max_file_num) 298 | { 299 | current_change=0; 300 | printf_with_time("无法在/sys/class/power_supply中的所有文件夹内找到constant_charge_current_max、fast_charge_current、thermal_input_current文件,有关电流的所有功能(包括“伪”旁路供电功能)失效!"); 301 | } 302 | if(!battery_status || !temp_file_num) 303 | { 304 | force_temp=0; 305 | if(battery_status && !temp_file_num) printf_with_time("无法在/sys/class/power_supply中的所有文件夹内找到temp文件,充电时强制显示28℃功能失效!"); 306 | else if(!battery_status && temp_file_num) printf_with_time("由于找不到/sys/class/power_supply/battery/status文件,充电时强制显示28℃功能失效!"); 307 | else printf_with_time("由于找不到/sys/class/power_supply/battery/status文件以及无法在/sys/class/power_supply中的所有文件夹内找到temp文件,充电时强制显示28℃功能失效!"); 308 | } 309 | if(force_temp || current_change) 310 | { 311 | temp_sensor_num = find_temp_sensor(temp_sensor); 312 | if(temp_sensor_num == 0) 313 | { 314 | if(force_temp) 315 | { 316 | printf_with_time("由于找不到程序支持的温度传感器,温度控制及充电时强制显示28℃功能失效!"); 317 | force_temp=0; 318 | } 319 | else printf_with_time("由于找不到程序支持的温度传感器,温度控制功能失效!"); 320 | if(!step_charge && !power_control && !force_temp && !current_change) 321 | { 322 | printf_with_time("所有的所需文件均不存在,完全不适配此手机,程序强制退出!"); 323 | exit(800); 324 | } 325 | } 326 | } 327 | else if(!step_charge && !power_control && !force_temp && !current_change) 328 | { 329 | printf_with_time("所有的所需文件均不存在,完全不适配此手机,程序强制退出!"); 330 | exit(1000); 331 | } 332 | if(current_change) for(i=0;i < current_max_file_num;i++) printf_with_time("找到电流文件:%s", current_max_file[i]); 333 | if(force_temp) for(i=0;i < temp_file_num;i++) printf_with_time("找到温度文件:%s", temp_file[i]); 334 | //如果有电流文件,则获取安卓版本,为以后“伪”旁路供电做准备 335 | if(current_change) can_get_foreground=check_android_version(); 336 | //创建一个子线程用来读取配置文件 337 | pthread_create(&thread2, NULL, &read_option_file, (void *)&read_option_time); 338 | pthread_detach(thread2); 339 | snprintf(current_max_char, 20, "%d", read_one_option("CURRENT_MAX")); 340 | snprintf(highest_temp_current_char, 20, "%d", read_one_option("HIGHEST_TEMP_CURRENT")); 341 | printf_with_time("文件检测完毕,程序开始运行"); 342 | //写入初值 343 | set_value("/sys/kernel/fast_charge/force_fast_charge", "1"); 344 | set_value("/sys/class/power_supply/battery/system_temp_level", "1"); 345 | set_value("/sys/class/power_supply/usb/boost_current", "1"); 346 | set_value("/sys/class/power_supply/battery/safety_timer_enabled", "0"); 347 | set_value("/sys/kernel/fast_charge/failsafe", "1"); 348 | set_value("/sys/class/power_supply/battery/allow_hvdcp3", "1"); 349 | set_value("/sys/class/power_supply/usb/pd_allowed", "1"); 350 | set_value("/sys/class/power_supply/battery/input_current_limited", "0"); 351 | set_value("/sys/class/power_supply/battery/input_current_settled", "1"); 352 | set_value("/sys/class/qcom-battery/restrict_chg", "0"); 353 | set_array_value(current_limit_file, current_limit_file_num, "-1"); 354 | charge_ctl("1"); 355 | //前期工作全部完成,程序正式开始运行 356 | while(1) 357 | { 358 | //读配置文件并赋值给程序内部变量 359 | snprintf(current_max_char, 20, "%d", read_one_option("CURRENT_MAX")); 360 | snprintf(highest_temp_current_char, 20, "%d", read_one_option("HIGHEST_TEMP_CURRENT")); 361 | //如果无法判断手机的充电状态,则很多功能无法实现,剩余代码很简单 362 | if(!battery_status) 363 | { 364 | //阶梯充电 365 | if(step_charge == 1) 366 | { 367 | if(read_one_option("STEP_CHARGING_DISABLED") == 1) (atoi(power) < read_one_option("STEP_CHARGING_DISABLED_THRESHOLD"))?step_charge_ctl("1"):step_charge_ctl("0"); 368 | else step_charge_ctl("1"); 369 | } 370 | else if(step_charge == 2) (read_one_option("STEP_CHARGING_DISABLED") == 1)?step_charge_ctl("0"):step_charge_ctl("1"); 371 | //“伪”旁路供电 372 | if(current_change && can_get_foreground) 373 | { 374 | bypass_charge_ctl(&thread1, &can_get_foreground, last_appname, &is_bypass, &screen_is_off, current_max_file, current_max_file_num); 375 | if(is_bypass && !screen_is_off) 376 | { 377 | sleep(read_one_option("CYCLE_TIME")); 378 | continue; 379 | } 380 | } 381 | //向电流文件写入配置文件中所设置的最大电流 382 | if(current_change) set_array_value(current_max_file, current_max_file_num, current_max_char); 383 | sleep(read_one_option("CYCLE_TIME")); 384 | continue; 385 | } 386 | if(force_temp && read_one_option("FORCE_TEMP") == 1 && !has_force_temp) has_force_temp=1; 387 | //读取手机电量 388 | read_file("/sys/class/power_supply/battery/capacity", power, sizeof(power)); 389 | //阶梯充电,无论是否在充电,都会跟随配置文件进行更改 390 | if(step_charge == 1) 391 | { 392 | if(read_one_option("STEP_CHARGING_DISABLED") == 1) (atoi(power) < read_one_option("STEP_CHARGING_DISABLED_THRESHOLD"))?step_charge_ctl("1"):step_charge_ctl("0"); 393 | else step_charge_ctl("1"); 394 | } 395 | else if(step_charge == 2) (read_one_option("STEP_CHARGING_DISABLED") == 1)?step_charge_ctl("0"):step_charge_ctl("1"); 396 | //读取充电状态 397 | read_file("/sys/class/power_supply/battery/status", charge, sizeof(charge)); 398 | //如果手机在充电,则根据配置文件进行相应操作 399 | if(strcmp(charge, "Discharging")) 400 | { 401 | //此处通过两个变量来确定上次循环时的充电状态以及是否是程序的第一次循环 402 | if(is_first_time || !last_charge_status) 403 | { 404 | printf_with_time("充电器已连接"); 405 | last_charge_status=1; 406 | is_first_time=0; 407 | } 408 | //充电时强制显示28度功能 409 | if(force_temp && read_one_option("FORCE_TEMP") == 1) set_array_value(temp_file, temp_file_num, "280"); 410 | else if(has_force_temp) set_temp(temp_sensor, temp_file, temp_file_num, 0); 411 | //电量控制功能 412 | if(power_control) powel_ctl(&last_charge_stop, &charge_is_stop); 413 | //如果电流文件存在且安卓版本大于等于7,则执行“伪”旁路供电函数 414 | if(current_change && can_get_foreground) 415 | { 416 | bypass_charge_ctl(&thread1, &can_get_foreground, last_appname, &is_bypass, &screen_is_off, current_max_file, current_max_file_num); 417 | //如果进入了“伪”旁路供电模式,则不执行下面的温度控制相关函数,直接进入下次循环 418 | if(is_bypass && !screen_is_off) 419 | { 420 | sleep(read_one_option("CYCLE_TIME")); 421 | continue; 422 | } 423 | } 424 | //温度控制功能 425 | if(read_one_option("TEMP_CTRL") == 1 && temp_sensor_num == 1 && current_change) 426 | { 427 | //读取温度传感器所获取的温度值 428 | read_file(temp_sensor, thermal, sizeof(thermal)); 429 | temp_int=atoi(thermal); 430 | //如果温度大于等于配置文件所设置的值,则打印相关信息并进入另一个循环中,等待相关事件的发生后退出二层循环 431 | if(temp_int >= read_one_option("TEMP_MAX")*1000) 432 | { 433 | printf_with_time("手机温度大于等于降低充电电流的温度阈值,限制充电电流为%sμA", highest_temp_current_char); 434 | //如果进入了“伪”旁路供电模式则退出此循环 435 | while(!is_bypass) 436 | { 437 | //每次循环重新读取配置文件及温度值 438 | snprintf(current_max_char, 20, "%d", read_one_option("CURRENT_MAX")); 439 | snprintf(highest_temp_current_char, 20, "%d", read_one_option("HIGHEST_TEMP_CURRENT")); 440 | set_array_value(current_limit_file, current_limit_file_num, "-1"); 441 | if(force_temp && read_one_option("FORCE_TEMP") == 1 && !has_force_temp) has_force_temp=1; 442 | read_file(temp_sensor, thermal, sizeof(thermal)); 443 | temp_int=atoi(thermal); 444 | //此tmp数组在读取配置文件的函数中,若配置文件的TEMP_MAX发生改变则会得到相应更改 445 | //作用是判断新的降低充电电流的温度阈值与旧的温度阈值的大小 446 | if(last_temp_max == -1) last_temp_max=read_one_option("TEMP_MAX"); 447 | if(last_temp_max != read_one_option("TEMP_MAX")) 448 | { 449 | last_temp_max=read_one_option("TEMP_MAX"); 450 | if(temp_int < read_one_option("TEMP_MAX")*1000) 451 | { 452 | printf_with_time("新的降低充电电流的温度阈值高于旧的温度阈值,且手机温度小于新的温度阈值,恢复充电电流为%sμA", current_max_char); 453 | break; 454 | } 455 | else printf_with_time("新的降低充电电流的温度阈值高于旧的温度阈值,但手机温度大于等于新的温度阈值,限制充电电流为%sμA", highest_temp_current_char); 456 | last_temp_max=read_one_option("TEMP_MAX"); 457 | } 458 | //判断手机充电状态 459 | read_file("/sys/class/power_supply/battery/status", charge, sizeof(charge)); 460 | if(!strcmp(charge, "Discharging")) 461 | { 462 | printf_with_time("充电器断开连接,恢复充电电流为%sμA", current_max_char); 463 | last_charge_status=0; 464 | break; 465 | } 466 | //判断温度是否小于恢复快充的温度阈值 467 | if(temp_int <= read_one_option("RECHARGE_TEMP")*1000) 468 | { 469 | printf_with_time("手机温度小于等于恢复快充的温度阈值,恢复充电电流为%sμA", current_max_char); 470 | break; 471 | } 472 | //判断温度控制功能是否关闭 473 | if(!read_one_option("TEMP_CTRL")) 474 | { 475 | printf_with_time("温控关闭,恢复充电电流为%sμA", current_max_char); 476 | break; 477 | } 478 | //阶梯充电 479 | if(step_charge == 1) 480 | { 481 | if(read_one_option("STEP_CHARGING_DISABLED") == 1) (atoi(power) < read_one_option("STEP_CHARGING_DISABLED_THRESHOLD"))?step_charge_ctl("1"):step_charge_ctl("0"); 482 | else step_charge_ctl("1"); 483 | } 484 | else if(step_charge == 2) (read_one_option("STEP_CHARGING_DISABLED") == 1)?step_charge_ctl("0"):step_charge_ctl("1"); 485 | //向电流文件中写入限制电流数值 486 | set_array_value(current_max_file, current_max_file_num, highest_temp_current_char); 487 | //充电时强制显示28度功能 488 | if(force_temp && read_one_option("FORCE_TEMP") == 1) set_array_value(temp_file, temp_file_num, "280"); 489 | else if(has_force_temp) set_temp(temp_sensor, temp_file, temp_file_num, 0); 490 | //电量控制功能 491 | if(power_control) powel_ctl(&last_charge_stop, &charge_is_stop); 492 | sleep(read_one_option("CYCLE_TIME")); 493 | } 494 | } 495 | } 496 | //向电流文件中写入最大充电电流 497 | if(current_change) set_array_value(current_max_file, current_max_file_num, current_max_char); 498 | } 499 | //如果手机未在充电,则只会刷新显示温度,以及若执行了获取前台应用包名的子线程,则取消此子线程 500 | else 501 | { 502 | //此处通过两个变量来确定上次循环时的充电状态以及是否是程序的第一次循环 503 | if(is_first_time) 504 | { 505 | printf_with_time("充电器未连接"); 506 | is_first_time=0; 507 | last_charge_status=0; 508 | } 509 | else if(last_charge_status) 510 | { 511 | printf_with_time("充电器断开连接"); 512 | last_charge_status=0; 513 | } 514 | //通过判断全局变量ForegroundAppName是否为空来判断获取前台应用包名的子线程是否在执行 515 | //若在执行,则取消此子线程,并清空ForegroundAppName 516 | pthread_mutex_lock((pthread_mutex_t *)&mutex_foreground_app); 517 | if(strlen((char *)ForegroundAppName)) 518 | { 519 | pthread_mutex_unlock((pthread_mutex_t *)&mutex_foreground_app); 520 | printf_with_time("手机未在充电状态,“伪”旁路供电功能暂时停用"); 521 | pthread_cancel(thread1); 522 | /* 523 | 在子线程中,使用sleep(5)来实现5秒循环获取前台应用 524 | 且在sleep(5)后紧跟pthread_testcancel()函数来检查子线程是否收到了取消信号 525 | 此处等待1秒以确保子线程能够处于等待5秒的过程中或使子线程完成等待5秒 526 | 这样在完成等待后就能直接在取消点取消子线程,从而使ForegroundAppName不会被子线程重新赋值 527 | */ 528 | sleep(1); 529 | pthread_mutex_lock((pthread_mutex_t *)&mutex_foreground_app); 530 | memset((void *)ForegroundAppName, 0, sizeof(ForegroundAppName)); 531 | } 532 | pthread_mutex_unlock((pthread_mutex_t *)&mutex_foreground_app); 533 | //此标识符代表手机是否处于“伪”旁路供电模式 534 | //如果在停止充电前手机处于“伪”旁路供电模式,则停止充电后将此标识符置0 535 | if(is_bypass) is_bypass=0; 536 | //因为断电也有可能是由电量控制引起的,所以此处执行电量控制函数 537 | if(power_control) powel_ctl(&last_charge_stop, &charge_is_stop); 538 | //此标识符代表手机是否通过此程序修改了电池温度 539 | //如果修改了,则电池温度无法再自动刷新,需要通过此程序进行刷新 540 | if(has_force_temp) 541 | { 542 | if(read_one_option("FORCE_TEMP") == 1) set_temp(temp_sensor, temp_file, temp_file_num, 1); 543 | else set_temp(temp_sensor, temp_file, temp_file_num, 0); 544 | } 545 | } 546 | sleep(read_one_option("CYCLE_TIME")); 547 | } 548 | return 0; 549 | } 550 | -------------------------------------------------------------------------------- /src/my_malloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef MI_MALLOC 4 | #include 5 | void *(*my_calloc)(size_t, size_t)=&mi_calloc; 6 | void *(*my_realloc)(void *, size_t)=&mi_realloc; 7 | void (*my_free)(void *)=&mi_free; 8 | #else 9 | #include 10 | void *(*my_calloc)(size_t, size_t)=&calloc; 11 | void *(*my_realloc)(void *, size_t)=&realloc; 12 | void (*my_free)(void *)=&free; 13 | #endif 14 | 15 | //完全释放动态申请的二级指针的内存 16 | void free_malloc_memory(char ***addr, int num) 17 | { 18 | if(addr == NULL || *addr == NULL) return; 19 | if(!num) num=1; 20 | for(int i=0;i < num;i++) 21 | { 22 | if((*addr)[i] == NULL) continue; 23 | my_free((*addr)[i]); 24 | (*addr)[i]=NULL; 25 | } 26 | my_free(*addr); 27 | *addr=NULL; 28 | } 29 | -------------------------------------------------------------------------------- /src/my_thread.c: -------------------------------------------------------------------------------- 1 | #include "my_thread.h" 2 | 3 | //创建两个互斥锁,供多线程使用 4 | volatile pthread_mutex_t mutex_foreground_app,mutex_options; 5 | -------------------------------------------------------------------------------- /src/options_linkedlist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "my_malloc.h" 5 | #include "options_linkedlist.h" 6 | #include "printf_with_time.h" 7 | #include "my_thread.h" 8 | 9 | 10 | //链表的头结点,只存储开始节点的地址 11 | ListNode options_head; 12 | 13 | //添加节点 14 | void insert_option(char *name, int value) 15 | { 16 | ListNode *next,*tmp=&options_head; 17 | next=(ListNode *)my_calloc(1, sizeof(ListNode)); 18 | strncpy(next->name, name, OPTION_NAME_MAX_SIZE-1); 19 | next->value=value; 20 | next->next=NULL; 21 | while(tmp->next) tmp=tmp->next; 22 | tmp->next=next; 23 | } 24 | 25 | //添加配置并将所有配置预先设为初始值 26 | void insert_all_option() 27 | { 28 | insert_option("CYCLE_TIME", 1); 29 | insert_option("FORCE_TEMP", 1); 30 | insert_option("CURRENT_MAX", 50000000); 31 | insert_option("STEP_CHARGING_DISABLED", 0); 32 | insert_option("TEMP_CTRL", 1); 33 | insert_option("POWER_CTRL", 0); 34 | insert_option("STEP_CHARGING_DISABLED_THRESHOLD", 15); 35 | insert_option("CHARGE_STOP", 95); 36 | insert_option("CHARGE_START", 80); 37 | insert_option("TEMP_MAX", 52); 38 | insert_option("HIGHEST_TEMP_CURRENT", 2000000); 39 | insert_option("RECHARGE_TEMP", 45); 40 | insert_option("BYPASS_CHARGE", 0); 41 | } 42 | 43 | //读取单个配置的值 44 | int read_one_option(char *name) 45 | { 46 | int value=-1; 47 | ListNode *node; 48 | pthread_mutex_lock((pthread_mutex_t *)&mutex_options); 49 | for(node=options_head.next;node;node=node->next) 50 | { 51 | if(!(strcmp(node->name, name))) 52 | { 53 | value=node->value; 54 | break; 55 | } 56 | } 57 | pthread_mutex_unlock((pthread_mutex_t *)&mutex_options); 58 | if(value < 0) 59 | { 60 | printf_with_time("无法获取变量,程序发生了内部错误,请立即前往Github进行反馈!"); 61 | exit(98765); 62 | } 63 | return value; 64 | } 65 | -------------------------------------------------------------------------------- /src/printf_with_time.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "printf_with_time.h" 7 | 8 | //获取本地时间并将时间转换为北京时间(UTC+8) 9 | void get_utc8_time(struct tm *ptm) 10 | { 11 | time_t cur_time; 12 | time(&cur_time); 13 | /* 14 | 新手特别容易犯的一个错误,形参的指针变量不能通过改变指向的地址来间接改变所存数据 15 | 在下一行代码中的体现就是不能通过 ptm=gmtime(&cur_time) 来直接将形参的指针变量重新指向另一块地址 16 | 只能通过memcpy等函数将其余地址所存数据复制到原形参指向的地址中,也就是只能直接改变原地址的数据 17 | */ 18 | memcpy(ptm, gmtime(&cur_time), sizeof(struct tm)); 19 | //手动将协调世界时转换为北京时间 20 | ptm->tm_year+=1900; 21 | ptm->tm_mon+=1; 22 | ptm->tm_hour+=8; 23 | if(ptm->tm_hour > 23) 24 | { 25 | ptm->tm_hour-=24; 26 | ptm->tm_mday+=1; 27 | switch(ptm->tm_mon) 28 | { 29 | case 1: case 3: case 5: case 7: case 8: case 10: case 12: 30 | if(ptm->tm_mday > 31) 31 | { 32 | ptm->tm_mday-=31; 33 | ptm->tm_mon+=1; 34 | } 35 | break; 36 | case 2: 37 | if(((ptm->tm_year%4 == 0) && (ptm->tm_year%100 != 0)) || (ptm->tm_year%400 == 0)) 38 | { 39 | if(ptm->tm_mday > 29) 40 | { 41 | ptm->tm_mday-=29; 42 | ptm->tm_mon+=1; 43 | } 44 | } 45 | else 46 | { 47 | if(ptm->tm_mday > 28) 48 | { 49 | ptm->tm_mday-=28; 50 | ptm->tm_mon+=1; 51 | } 52 | } 53 | break; 54 | default: 55 | if(ptm->tm_mday > 30) 56 | { 57 | ptm->tm_mday-=30; 58 | ptm->tm_mon+=1; 59 | } 60 | break; 61 | } 62 | if(ptm->tm_mon > 12) 63 | { 64 | ptm->tm_mon-=12; 65 | ptm->tm_year+=1; 66 | } 67 | } 68 | } 69 | 70 | //以printf的标准对函数的参数进行检查、格式化,并在字符串前面加上时间 71 | void printf_with_time(const char *format, ...) __attribute__((__format__(__printf__, 1, 2))); 72 | void printf_with_time(const char *format, ...) 73 | { 74 | char buffer[1024]={0}; 75 | struct tm time_utc8_now; 76 | va_list ap; 77 | //使用vsnprintf函数拼接格式化字符串和可变参数 78 | va_start(ap, format); 79 | vsnprintf(buffer, 1024, format, ap); 80 | va_end(ap); 81 | get_utc8_time(&time_utc8_now); 82 | //在拼接后的字符串前面加上时间 83 | printf("[ %04d.%02d.%02dT%02d:%02d:%02d UTC+8 ] %s\n", time_utc8_now.tm_year, time_utc8_now.tm_mon, time_utc8_now.tm_mday, time_utc8_now.tm_hour, time_utc8_now.tm_min, time_utc8_now.tm_sec, buffer); 84 | fflush(stdout); 85 | } 86 | -------------------------------------------------------------------------------- /src/read_option_file.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "read_option_file.h" 9 | #include "printf_with_time.h" 10 | 11 | /* 12 | 读取配置文件并赋值给程序内部变量 13 | */ 14 | void *read_option_file(void *arg) 15 | { 16 | //文件修改时间需持续存储,所以在循环体外定义 17 | uint option_last_modify_time=0, sleep_time=*(int *)arg; 18 | while(1) 19 | { 20 | //在循环体内定义变量,这样变量仅存在于单次循环,每次循环结束后变量自动释放,循环开始时变量重新定义 21 | FILE *fc; 22 | char option_tmp[42]={0},option[100]={0},*value=NULL; 23 | uchar opt=0,i=0,option_quantity=1; 24 | int new_value=0; 25 | struct stat statbuf; 26 | ListNode *node=options_head.next,*tmp=options_head.next; 27 | if(node == NULL || tmp == NULL) 28 | { 29 | printf_with_time("存储配置信息的链表中没有节点,程序强制停止运行!"); 30 | exit(9988); 31 | } 32 | while((tmp=tmp->next) != NULL) option_quantity++; 33 | //不定长数组无法在定义时初始化为全0,所以后续会使用memset进行清零 34 | uchar value_stat[option_quantity]; 35 | check_read_file(option_file); 36 | //先获取文件修改时间,若本次的文件修改时间与上次相等,证明配置文件未修改,跳过读取 37 | stat(option_file, &statbuf); 38 | if(statbuf.st_mtime == option_last_modify_time) 39 | { 40 | sleep(sleep_time); 41 | continue; 42 | } 43 | memset(value_stat, 0, sizeof(value_stat)); 44 | pthread_mutex_lock((pthread_mutex_t *)&mutex_options); 45 | fc=fopen(option_file, "rt"); 46 | while(fgets(option, sizeof(option), fc) != NULL) 47 | { 48 | line_feed(option); 49 | //跳过以英文井号开头的行及空行 50 | if(!strlen(option) || (strstr(option, "#") != NULL && !strstr(option, "#"))) continue; 51 | for(opt=0,node=options_head.next;node;opt++,node=node->next) 52 | { 53 | //将配置名与等号进行拼接,用来进行匹配 54 | snprintf(option_tmp, 42, "%s=", node->name); 55 | if(strstr(option, option_tmp) == NULL) continue; 56 | //value_stat数组存储配置文件中每个变量值的状态,详情直接看后面判断value_stat数组的值的相关代码 57 | value_stat[opt]=10; 58 | //判断变量值是否合法,合法则对程序内部变量进行赋值,否则将状态存入value_stat数组中 59 | if(!strcmp(option, option_tmp)) value_stat[opt]=1; 60 | else 61 | { 62 | value=option+strlen(option_tmp); 63 | for(i=0;i < strlen(value);i++) 64 | { 65 | if((value[i] < '0' || value[i] > '9') && ((!i && (value[i] != '-' || strlen(value) == 1)) || i)) 66 | { 67 | value_stat[opt]=2; 68 | break; 69 | } 70 | } 71 | } 72 | if(value_stat[opt] != 10) continue; 73 | new_value=atoi(value); 74 | if(new_value < 0) value_stat[opt]=3; 75 | else if(!strcmp((char *)(node->name), "CYCLE_TIME") && !new_value) value_stat[opt]=4; 76 | if(value_stat[opt] == 10 && node->value != new_value) 77 | { 78 | node->value=new_value; 79 | value_stat[opt]=100; 80 | } 81 | } 82 | } 83 | fclose(fc); 84 | fc=NULL; 85 | for(opt=0,node=options_head.next;node;opt++,node=node->next) 86 | { 87 | //通过判断是否第一次运行来进行不同的字符串输出 88 | if(option_last_modify_time) 89 | { 90 | if(value_stat[opt] == 0) printf_with_time("配置文件中%s不存在,故程序沿用上一次的值%d", node->name, node->value); 91 | else if(value_stat[opt] == 1) printf_with_time("新%s的值为空,故程序沿用上一次的值%d", node->name, node->value); 92 | else if(value_stat[opt] == 2) printf_with_time("新%s的值不是由纯数字组成,故程序沿用上一次的值%d", node->name, node->value); 93 | else if(value_stat[opt] == 3) printf_with_time("新%s的值小于0,这是不被允许的,故程序沿用上一次的值%d", node->name, node->value); 94 | else if(value_stat[opt] == 4) printf_with_time("新%s的值为0,这是不被允许的,故程序沿用上一次的值%d", node->name, node->value); 95 | else if(value_stat[opt] == 100) printf_with_time("%s的值更改为%d", node->name, node->value); 96 | } 97 | else 98 | { 99 | if(value_stat[opt] == 0) printf_with_time("配置文件中%s不存在,故程序使用默认值%d", node->name, node->value); 100 | else if(value_stat[opt] == 1) printf_with_time("配置文件中%s的值为空,故程序使用默认值%d", node->name, node->value); 101 | else if(value_stat[opt] == 2) printf_with_time("配置文件中%s的值不是由纯数字组成,故程序使用默认值%d", node->name, node->value); 102 | else if(value_stat[opt] == 3) printf_with_time("配置文件中%s的值小于0,这是不被允许的,故程序使用默认值%d", node->name, node->value); 103 | else if(value_stat[opt] == 4) printf_with_time("配置文件中%s的值为0,这是不被允许的,故程序使用默认值%d", node->name, node->value); 104 | } 105 | } 106 | option_last_modify_time=statbuf.st_mtime; 107 | pthread_mutex_unlock((pthread_mutex_t *)&mutex_options); 108 | sleep(sleep_time); 109 | } 110 | return NULL; 111 | } 112 | -------------------------------------------------------------------------------- /src/some_ctrl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "some_ctrl.h" 7 | #include "options_linkedlist.h" 8 | #include "value_set.h" 9 | #include "my_malloc.h" 10 | #include "foreground_app.h" 11 | #include "printf_with_time.h" 12 | 13 | //阶梯充电的控制,1为开启0为关闭 14 | void step_charge_ctl(char *value) 15 | { 16 | check_read_file("/sys/class/power_supply/battery/step_charging_enabled"); 17 | set_value("/sys/class/power_supply/battery/step_charging_enabled", value); 18 | set_value("/sys/class/power_supply/battery/sw_jeita_enabled", value); 19 | } 20 | 21 | //控制能否进行充电,1为充电0为暂停充电 22 | void charge_ctl(char *i) 23 | { 24 | set_value("/sys/class/power_supply/battery/charging_enabled", i); 25 | set_value("/sys/class/power_supply/battery/battery_charging_enabled", i); 26 | if(atoi(i)) 27 | { 28 | set_value("/sys/class/power_supply/battery/input_suspend", "0"); 29 | set_value("/sys/class/qcom-battery/restricted_charging", "0"); 30 | } 31 | else 32 | { 33 | set_value("/sys/class/power_supply/battery/input_suspend", "1"); 34 | set_value("/sys/class/qcom-battery/restricted_charging", "1"); 35 | } 36 | } 37 | 38 | //电量控制 39 | void powel_ctl(int *last_charge_stop, int *charge_is_stop) 40 | { 41 | int charge_stop=read_one_option("CHARGE_STOP"),power_int=0; 42 | char power[10]; 43 | if(*last_charge_stop == -1) *last_charge_stop=charge_stop; 44 | if(read_one_option("POWER_CTRL") == 1) 45 | { 46 | read_file("/sys/class/power_supply/battery/capacity", power, sizeof(power)); 47 | power_int=atoi(power); 48 | if(*last_charge_stop != charge_stop && *charge_is_stop) 49 | { 50 | if(power_int < charge_stop) 51 | { 52 | printf_with_time("手机当前电量为%d%%,小于新的电量阈值,恢复充电", power_int); 53 | *charge_is_stop=0; 54 | charge_ctl("1"); 55 | } 56 | else 57 | { 58 | printf_with_time("手机当前电量为%d%%,大于等于新的电量阈值,保持停止充电状态", power_int); 59 | charge_ctl("0"); 60 | } 61 | *last_charge_stop=charge_stop; 62 | } 63 | if(power_int >= charge_stop && !(*charge_is_stop)) 64 | { 65 | printf_with_time("当前电量为%d%%,大于等于停止充电的电量阈值,停止充电", power_int); 66 | *charge_is_stop=1; 67 | charge_ctl("0"); 68 | } 69 | if(power_int <= read_one_option("CHARGE_START") && *charge_is_stop) 70 | { 71 | printf_with_time("当前电量为%d%%,小于等于恢复充电的电量阈值,恢复充电", power_int); 72 | *charge_is_stop=0; 73 | charge_ctl("1"); 74 | } 75 | } 76 | else 77 | { 78 | if(*charge_is_stop) 79 | { 80 | printf_with_time("电量控制关闭,恢复充电"); 81 | *charge_is_stop=0; 82 | } 83 | if(*last_charge_stop != charge_stop) *last_charge_stop=charge_stop; 84 | charge_ctl("1"); 85 | } 86 | } 87 | 88 | /* 89 | “伪”旁路充电控制 90 | thread1为用来存储进程信息的pthread_t结构体 91 | android_version为安卓版本 92 | last_appname为上一次获取到的前台应用包名 93 | is_bypass为上一次获取到的前台应用是否位于配置列表中,与主函数进行通信 94 | screen_is_off为手机是否处于锁屏状态,与主函数进行通信 95 | current_max_file为存储电流文件的二级指针变量,与current_max_file_num配套使用 96 | current_max_file_num为电流文件的个数 97 | */ 98 | void bypass_charge_ctl(pthread_t *thread1, int *android_version, char *last_appname, int *is_bypass, int *screen_is_off, char **current_max_file, int current_max_file_num) 99 | { 100 | char name[APP_PACKAGE_NAME_MAX_SIZE]={0}; 101 | uchar in_list=0; 102 | FILE *fp; 103 | static char **bypass_app_package_name=NULL; 104 | static uint bypass_file_last_modify_time=0,bypass_app_num=0; 105 | struct stat statbuf; 106 | /* 107 | 为了不使获取前台应用包名拖累主程序的执行效率,所以使用了子线程方案 108 | 如果配置文件的BYPASS_CHARGE值为1且ForegroundAppName值为空(没有子线程正在执行),则创建子线程 109 | 此子线程用来获取前台应用包名 110 | */ 111 | pthread_mutex_lock((pthread_mutex_t *)&mutex_foreground_app); 112 | if(read_one_option("BYPASS_CHARGE") == 1 && !strlen((char *)ForegroundAppName)) 113 | { 114 | strncpy((char *)ForegroundAppName, "chase535", APP_PACKAGE_NAME_MAX_SIZE-1); 115 | pthread_create(thread1, NULL, get_foreground_appname, (void *)android_version); 116 | pthread_detach(*thread1); 117 | } 118 | //如果ForegroundAppName值不是初始值,则代表获取到了前台应用包名,则进行匹配并作出相应行动 119 | else if(read_one_option("BYPASS_CHARGE") == 1 && strlen((char *)ForegroundAppName) && strcmp((char *)ForegroundAppName, "chase535")) 120 | { 121 | //如果手机从锁屏状态恢复且在锁屏前处于“伪”旁路供电模式,则恢复此模式 122 | if(strcmp((char *)ForegroundAppName, "screen_is_off")) 123 | { 124 | if(*screen_is_off) 125 | { 126 | if(*is_bypass) printf_with_time("手机屏幕开启,恢复“伪”旁路供电模式"); 127 | *screen_is_off=0; 128 | } 129 | //读取“伪”旁路供电的配置文件 130 | check_read_file(bypass_charge_file); 131 | stat(option_file, &statbuf); 132 | if(statbuf.st_mtime != bypass_file_last_modify_time) 133 | { 134 | bypass_app_num=0; 135 | if(bypass_app_package_name != NULL) free_malloc_memory(&bypass_app_package_name, bypass_app_num); 136 | bypass_app_package_name=(char **)my_calloc(1, sizeof(char *)); 137 | fp=fopen(bypass_charge_file, "rt"); 138 | while(fgets(name, sizeof(name), fp) != NULL) 139 | { 140 | line_feed(name); 141 | //跳过以英文井号开头的行及空行 142 | if(!strlen(name) || (strstr(name, "#") != NULL && !strstr(name, "#"))) continue; 143 | bypass_app_num++; 144 | bypass_app_package_name=(char **)my_realloc(bypass_app_package_name, sizeof(char *)*bypass_app_num); 145 | bypass_app_package_name[bypass_app_num-1]=(char *)my_calloc(1, sizeof(char)*APP_PACKAGE_NAME_MAX_SIZE); 146 | strncpy(bypass_app_package_name[bypass_app_num-1], name, APP_PACKAGE_NAME_MAX_SIZE-1); 147 | } 148 | fclose(fp); 149 | fp=NULL; 150 | } 151 | //判断前台应用包名是否在配置文件中 152 | for(uint i=0;i < bypass_app_num; i++) 153 | { 154 | if(!strcmp((char *)ForegroundAppName, bypass_app_package_name[i])) 155 | { 156 | in_list=1; 157 | break; 158 | } 159 | } 160 | //如果前台应用包名在配置文件中 161 | if(in_list) 162 | { 163 | //如果之前不在“伪”旁路供电模式而切换应用后在了,就打印相关信息 164 | if(!(*is_bypass)) 165 | { 166 | printf_with_time("当前前台应用为%s,位于“伪”旁路供电配置列表中,进入“伪”旁路供电模式", ForegroundAppName); 167 | *is_bypass=1; 168 | } 169 | //如果之前在“伪”旁路供电模式而切换应用后还在,就打印相关信息 170 | else if(strcmp(last_appname, (char *)ForegroundAppName)) printf_with_time("前台应用切换为%s,位于“伪”旁路供电配置列表中,保持“伪”旁路供电模式", ForegroundAppName); 171 | //限制电流,“伪”旁路供电 172 | set_array_value(current_max_file, current_max_file_num, BYPASS_CHARGE_CURRENT); 173 | } 174 | else 175 | { 176 | //如果之前在“伪”旁路供电模式而切换应用后不在,就打印相关信息 177 | if(*is_bypass) 178 | { 179 | //分为两种情况,一种为未切换前台应用但应用包名从“伪”旁路供电配置列表中移除,一种为切换到了“伪”旁路供电配置列表中没有的应用 180 | if(strcmp(last_appname, (char *)ForegroundAppName)) printf_with_time("前台应用切换为%s,不在“伪”旁路供电配置列表中,恢复正常充电模式", ForegroundAppName); 181 | else printf_with_time("%s已从“伪”旁路供电配置列表中移除,恢复正常充电模式", ForegroundAppName); 182 | *is_bypass=0; 183 | } 184 | } 185 | strncpy(last_appname, (char *)ForegroundAppName, APP_PACKAGE_NAME_MAX_SIZE-1); 186 | } 187 | else 188 | { 189 | //如果手机进入锁屏状态且在锁屏前处于“伪”旁路供电模式,则暂时恢复正常充电模式 190 | if(!(*screen_is_off)) 191 | { 192 | if(*is_bypass) printf_with_time("手机屏幕关闭,暂时进入正常充电模式"); 193 | *screen_is_off=1; 194 | } 195 | } 196 | } 197 | //子线程结束运行或者获取不到前台应用包名,则清空上一次获取到的前台应用包名并恢复正常充电模式 198 | else 199 | { 200 | if(strlen(last_appname)) memset(last_appname, 0, APP_PACKAGE_NAME_MAX_SIZE*sizeof(char)); 201 | if(*is_bypass) *is_bypass=0; 202 | } 203 | pthread_mutex_unlock((pthread_mutex_t *)&mutex_foreground_app); 204 | } 205 | -------------------------------------------------------------------------------- /src/value_set.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "value_set.h" 8 | 9 | /* 10 | 向文件写入数据 11 | 若文件存在且不可写,尝试修改权限后重新检查是否可写 12 | 若文件不存在或修改权限后仍不可写,则跳过本次写操作 13 | */ 14 | void set_value(char *file, char *numb) 15 | { 16 | if(!access(file, F_OK)) 17 | { 18 | FILE *fn; 19 | struct stat statbuf; 20 | stat(file, &statbuf); 21 | char content[statbuf.st_size+1]; 22 | fn=fopen(file, "rt+"); 23 | if(fn != NULL) goto write_data; 24 | else 25 | { 26 | //权限0644不得简写成644 27 | chmod(file, 0644); 28 | fn=fopen(file, "rt+"); 29 | if(fn != NULL) 30 | { 31 | write_data: 32 | fgets(content, statbuf.st_size+1, fn); 33 | line_feed(content); 34 | //先判断文件内容与所写内容是否一致,若不一致才进行写入 35 | if(strcmp(content, numb)) 36 | { 37 | rewind(fn); 38 | fputs(numb, fn); 39 | } 40 | fclose(fn); 41 | fn=NULL; 42 | } 43 | } 44 | } 45 | } 46 | 47 | //向二级指针所指向的文件们写入数据 48 | void set_array_value(char **file, int num, char *value) 49 | { 50 | for(int i=0;i < num;i++) set_value(file[i], value); 51 | } 52 | 53 | /* 54 | 向二级指针所指向的温度文件们写入温度 55 | tempwall为是否启用超过一定温度时强制向温度文件写入28℃ 56 | */ 57 | void set_temp(char *temp_sensor, char **temp_file, int temp_file_num, uchar tempwall) 58 | { 59 | char thermal[15]={0},bat_temp[6]={0}; 60 | int temp_int=0; 61 | //读取温度文件 62 | read_file(temp_sensor, thermal, sizeof(thermal)); 63 | temp_int=atoi(thermal); 64 | //若温度为正数,则将温度扩展为6位数并取前3位数 65 | //若温度为负数,则将温度扩展为负号+5位数并取负号+前3位数 66 | (temp_int < 0)?snprintf(bat_temp, 5, "%06d", temp_int):snprintf(bat_temp, 4, "%05d", temp_int); 67 | temp_int=atoi(bat_temp); 68 | snprintf(bat_temp, 6, "%d", temp_int); 69 | //如果tempwall为1,则判断温度是否超过指定值,若超过则强制显示28度,否则显示正常温度 70 | //如果tempwall为0,则永远显示正常温度 71 | if(tempwall) (temp_int >= 450)?set_array_value(temp_file, temp_file_num, "280"):set_array_value(temp_file, temp_file_num, bat_temp); 72 | else set_array_value(temp_file, temp_file_num, bat_temp); 73 | } 74 | -------------------------------------------------------------------------------- /update_channel/changelog.md: -------------------------------------------------------------------------------- 1 | # v68 2 | 3 | ### Changelog 4 | 5 | 1.mimalloc切换为dev-slice分支 6 | 7 | 2.新增判断链表中是否有节点 8 | 9 | 3.优化代码 10 | 11 | -------------------------------------------------------------------------------- /update_channel/turbo-charge.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "v68", 3 | "versionCode": "68", 4 | "zipUrl": "https://gitee.com/chase535/turbo-charge/raw/main/update_channel/turbo-charge.zip", 5 | "changelog": "https://gitee.com/chase535/turbo-charge/raw/main/update_channel/changelog.md" 6 | } 7 | -------------------------------------------------------------------------------- /update_channel/turbo-charge.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chase535/turbo-charge/c8a2a8dab31546ecdce4615789e0bf50edf8a730/update_channel/turbo-charge.zip --------------------------------------------------------------------------------