在Settings->Battery新增选项,以控制电量保持在设定的百分比:
Otimização da vida útil da bateria #电池寿命的优化
Carga Completa ativada #满载启动
->Otimização da vida útil da bateria #电池寿命的优化
->Carga Completa #满载
Carregue seu dispositivo até 100% #为您的设备充电至100%
->Carga Otimizada (Recomendado) #优化负载(推荐)
Carregue seu dispositivo até 85% #为您的设备充电,最高可达85%
->Carga Moderada #中等负荷
Carregue seu dispositivo até 60% #将您的设备充电至60%
Para preservar a vida útil da bateria, mantenha sempre Seu nível entre 20% e 80%. Recomenda-se usar o modo Carga Otimizada.
#为了延长电池寿命,请始终将电量保持在20%到80%之间。建议使用优化的加载模式。
Android 广播Broadcast的两种注册方式静态和动态
方法举例:
1 2 3 4 5 6 7 8 9 10 11 | import android.provider.Settings; //设置系统配置文件中的数据,第一个参数固定的,但是需要上下文,第二个参数是保存的Key,第三个参数是保存的value boolean changeBluetoothName = Settings.System.putInt(getContentResolver(), "changeBluetoothName", 1); //获取系统配置文件中的数据,第一个参数固定的,但是需要上下文,第二个参数是之前保存的Key,第三个参数表示如果没有这个key的情况的默认值 int blueFlag = Settings.System.getInt(getContentResolver(), "changeBluetoothName", 0);
//据说这个系统数据库的位置是: //data/data/com.android.providers.settings/databases/
//数据库控制的代码: //frameworks\base\packages\SettingsProvider\src\com\android\providers\settings的DatabaseHelper类里面 |
\frameworks\base\core\java\android\provider\Settings.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | /** * The Settings provider contains global system-level device preferences. */ public final class Settings { /** * System settings, containing miscellaneous system preferences. This * table holds simple name/value pairs. There are convenience * functions for accessing individual settings entries. */ public static final class System extends NameValueTable { public static final String SHOW_BATTERY_PERCENT = "status_bar_show_battery_percent"; public static final String CHARGE_MODE = "charge_mode"; //cy add chargemode limit 100 or 85 or 60 ... ... } } |
\frameworks\base\api\current.txt
1 2 3 4 5 6 7 8 9 | // Signature format: 2.0 package android { ... ... public static final class Settings.System extends android.provider.Settings.NameValueTable { ctor public Settings.System(); ... ... field public static final String CHARGE_MODE = "charge_mode"; } } |
\frameworks\base\non-updatable-api\current.txt
1 2 3 4 5 6 7 8 9 | // Signature format: 2.0 package android { ... ... public static final class Settings.System extends android.provider.Settings.NameValueTable { ctor public Settings.System(); ... ... field public static final String CHARGE_MODE = "charge_mode"; } } |
\vendor\mediatek\proprietary\packages\apps\MtkSettings\res\values\strings.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?xml version="1.0" encoding="utf-8"?> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> ... ... <!-- [CHAR_LIMIT=40] Battery percentage: Title --> <string name="battery_percentage">Battery percentage</string> ... ... <string name="charging_mode">Optimize battery life active</string> <string name="charging_mode_summary">Full load active</string>
<string name="chargeModeTitle">Optimize battery life</string> <string name="chargeMode100_title">Full load</string> <string name="chargeMode100_summary">Charge to 100%</string> <string name="chargeMode85_title">Optimal load (Recomendado)</string> <string name="chargeMode85_summary">Charge to 85%</string> <string name="chargeMode60_title">Middle load</string> <string name="chargeMode60_summary">Charge to 60%</string> <string name="chargeModeMessage" formatted="false">In order to prolong the battery life, please keep the power between 20% and 80% at all times. An optimized loading mode is recommended.</string> </resources> |
\vendor\mediatek\proprietary\packages\apps\MtkSettings\res\values-pt-rPT\strings.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> ... ... <string name="charging_mode" msgid="8345490568291778641">Otimização da vida útil da bateria</string> <string name="charging_mode_summary" msgid="8345490568291778642">Carga Completa ativada</string> <string name="chargeModeTitle" msgid="8345490568291778643">Otimização da vida útil da bateria</string> <string name="chargeMode100_title" msgid="8345490568291778644">Carga Completa</string> <string name="chargeMode100_summary" msgid="8345490568291778645">Carregue seu dispositivo até 100%</string> <string name="chargeMode85_title" msgid="8345490568291778646">Carga Otimizada (Recomendado)</string> <string name="chargeMode85_summary" msgid="8345490568291778647">Carregue seu dispositivo até 85%</string> <string name="chargeMode60_title" msgid="8345490568291778648">Carga Moderada</string> <string name="chargeMode60_summary" msgid="8345490568291778649">Carregue seu dispositivo até 60%</string> <string name="chargeModeMessage" msgid="8345490568291778650" formatted="false">Para preservar a vida útil da bateria, mantenha sempre Seu nível entre 20% e 80%. Recomenda-se usar o modo Carga Otimizada.</string> </resources> |
\vendor\mediatek\proprietary\packages\apps\MtkSettings\res\values-zh-rCN\strings.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> ... ... <string name="charging_mode" msgid="8345490568291778641">电池寿命的优化激活</string> <string name="charging_mode_summary" msgid="8345490568291778642">满载激活</string> <string name="chargeModeTitle" msgid="8345490568291778643">电池寿命的优化</string> <string name="chargeMode100_title" msgid="8345490568291778644">满载</string> <string name="chargeMode100_summary" msgid="8345490568291778645">为您的设备充电至100%</string> <string name="chargeMode85_title" msgid="8345490568291778646">优化负载(推荐)</string> <string name="chargeMode85_summary" msgid="8345490568291778647">为您的设备充电,最高可达85%</string> <string name="chargeMode60_title" msgid="8345490568291778648">中等负荷</string> <string name="chargeMode60_summary" msgid="8345490568291778649">将您的设备充电至60%</string> <string name="chargeModeMessage" msgid="8345490568291778650" formatted="false">为了延长电池寿命,请始终将电量保持在20%到80%之间。建议使用优化的加载模式。</string> </resources> |
\vendor\mediatek\proprietary\packages\apps\MtkSettings\res\xml\power_usage_summary.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="power_usage_summary_screen" android:title="@string/power_usage_summary_title" settings:keywords="@string/keywords_battery"> ... ... <SwitchPreference android:key="battery_percentage" android:title="@string/battery_percentage" android:summary="@string/battery_percentage_description" settings:controller="com.android.settings.display.BatteryPercentagePreferenceController" /> <!-- cy add start -->> <Preference android:key="charging_mode" android:title="@string/charging_mode" android:summary="@string/charging_mode_summary" settings:controller="com.android.settings.fuelgauge.batterytip.ChargingModePreferenceController" /> <!-- cy add end -->> <com.android.settings.fuelgauge.PowerGaugePreference android:key="last_full_charge" android:title="@string/battery_last_full_charge" android:selectable="false" settings:allowDividerAbove="true" />
<com.android.settings.fuelgauge.PowerGaugePreference android:key="screen_usage" android:title="@string/device_screen_usage" android:selectable="false" />
<com.android.settingslib.widget.FooterPreference android:key="power_usage_footer" android:title="@string/battery_footer_summary" android:selectable="false" settings:searchable="false"/> </PreferenceScreen> |
\vendor\mediatek\proprietary\packages\apps\MtkSettings\res\layout\chargemode_radiobutton.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" xmlns:android="http://schemas.android.com/apk/res/android" > <RadioGroup android:id="@+id/chargeMode_radio" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginRight="20dp" android:layout_marginTop="20dp" android:layout_marginBottom="20dp" android:orientation="vertical"> <RadioButton android:id="@+id/charge_mode100" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/chargeMode100_title" android:textSize="15dp" android:textStyle="bold"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="31dp" android:text="@string/chargeMode100_summary"/> <RadioButton android:id="@+id/charge_mode85" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/chargeMode85_title" android:textSize="15dp" android:textStyle="bold"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="31dp" android:text="@string/chargeMode85_summary"/> <RadioButton android:id="@+id/charge_mode60" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/chargeMode60_title" android:textSize="15dp" android:textStyle="bold"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="31dp" android:text="@string/chargeMode60_summary"/> </RadioGroup> <TextView android:id="@+id/charge_mode_message" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="25dp" android:layout_marginRight="25dp" android:text="@string/chargeModeMessage" android:textSize="14dp" /> </LinearLayout> |
\vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\fuelgauge\batterytip\ChargingModePreferenceController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
package com.android.settings.fuelgauge.batterytip;
import static android.provider.Settings.System.CHARGE_MODE;
import android.content.Context; import android.content.Intent; //cy import android.text.TextUtils; import androidx.preference.Preference; import com.android.settings.R; import android.provider.Settings; import com.android.settings.core.BasePreferenceController;
import android.app.AlertDialog; import android.content.DialogInterface; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.RadioButton; import android.widget.RadioGroup;
/** * Preference controller to control the battery manager */ public class ChargingModePreferenceController extends BasePreferenceController { private static final String KEY_CHARGING_MODE = "charging_mode"; private static AlertDialog chargeModeDialog; private static AlertDialog.Builder chargeModeDialogBuilder; public ChargingModePreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); } @Override public int getAvailabilityStatus() { return AVAILABLE_UNSEARCHABLE; } @Override public boolean handlePreferenceTreeClick(Preference preference) { if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) { return false; } showChargeModeDialog(); return true; } private void showChargeModeDialog(){ if(chargeModeDialog != null){ chargeModeDialog.show(); return; } LayoutInflater inflaterCharge = LayoutInflater.from(mContext); View viewChargeMode = inflaterCharge.inflate(R.layout.chargemode_radiobutton,null); RadioGroup chargeModeRadioGroup = viewChargeMode.findViewById(R.id.chargeMode_radio); RadioButton chargeMode100 = viewChargeMode.findViewById(R.id.charge_mode100); RadioButton chargeMode85 = viewChargeMode.findViewById(R.id.charge_mode85); RadioButton chargeMode60 = viewChargeMode.findViewById(R.id.charge_mode60); int chargeModeCheck = Settings.System.getInt(mContext.getContentResolver(), CHARGE_MODE, 100); if(chargeModeCheck == 60){ chargeMode60.setChecked(true); } else if(chargeModeCheck == 85){ chargeMode85.setChecked(true); } else{ chargeMode100.setChecked(true); } chargeModeRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, int checkedId) { if (checkedId == R.id.charge_mode100){ //保存变量到Settings 数据库中 Settings.System.putInt(mContext.getContentResolver(), CHARGE_MODE, 100); } if (checkedId == R.id.charge_mode85){ Settings.System.putInt(mContext.getContentResolver(), CHARGE_MODE, 85); } if (checkedId == R.id.charge_mode60){ Settings.System.putInt(mContext.getContentResolver(), CHARGE_MODE, 60); } // Intent intent = new Intent("Charge.mode.changed"); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); intent.addFlags(0x01000000 | 0x00400000); mContext.sendBroadcast(intent); } }); chargeModeDialogBuilder = new AlertDialog.Builder(mContext,AlertDialog.THEME_DEVICE_DEFAULT_LIGHT); chargeModeDialogBuilder.setTitle(R.string.chargeModeTitle); chargeModeDialogBuilder.setView(viewChargeMode); chargeModeDialogBuilder.setNegativeButton("CANCELAR", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { chargeModeDialog.cancel(); } }); chargeModeDialog = chargeModeDialogBuilder.create(); chargeModeDialog.getWindow().setGravity(Gravity.CENTER); // chargeModeDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG); chargeModeDialog.show(); } } |
\frameworks\base\services\core\java\com\android\server\BatteryService.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | import static android.provider.Settings.System.CHARGE_MODE; //cy add import java.io.FileWriter; //cy add import java.io.FileNotFoundException; //cy add import android.content.BroadcastReceiver; //cy add import android.content.IntentFilter; //cy add
public final class BatteryService extends SystemService { ... ... private static int chargeModeLimit;//cy add private static boolean isFirstStart = true;//cy add ... ... public BatteryService(Context context) { super(context); ... ... mContext.registerReceiver(new ChargeModeChargedReceiver() ,new IntentFilter("Charge.mode.changed"));//cy ... ... } //cy add start private int fileWrite(String fileName, String buffer) { int i = -1; try { File file = new File(fileName); if(!file.exists()){ if(!file.getParentFile().exists()){ file.getParentFile().mkdirs(); } file.createNewFile(); } FileWriter fileWriter = new FileWriter(fileName); fileWriter.write(buffer); //android.util.Log.d("cy_batteryservice","write file end"); fileWriter.close(); i = 0; } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return i; } private void batteryCapacityCtrl(){ int chargeModeLimit = Settings.System.getInt(mContext.getContentResolver(), CHARGE_MODE, 100); boolean isCharging = (mHealthInfo.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING); if((mHealthInfo.batteryLevel >= chargeModeLimit) && isCharging){ fileWrite("/sys/devices/platform/mt-battery/BatteryCapacityCtrl","1"); }else if((mHealthInfo.batteryLevel < chargeModeLimit) && !isCharging){ fileWrite("/sys/devices/platform/mt-battery/BatteryCapacityCtrl","0"); } } private class ChargeModeChargedReceiver extends BroadcastReceiver{ @Override public void onReceive(Context context, Intent intent) { // android.util.Log.d("ChargeModeChargedReceiver", "onReceive: intent="+intent.getAction()); batteryCapacityCtrl(); } } //cy add end private void processValuesLocked(boolean force) { boolean logOutlier = false; long dischargeDuration = 0;
mBatteryLevelCritical = mHealthInfo.batteryStatus != BatteryManager.BATTERY_STATUS_UNKNOWN && mHealthInfo.batteryLevel <= mCriticalBatteryLevel; if (mHealthInfo.chargerAcOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_AC; } else if (mHealthInfo.chargerUsbOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_USB; } else if (mHealthInfo.chargerWirelessOnline) { mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS; } else { mPlugType = BATTERY_PLUGGED_NONE; } batteryCapacityCtrl();//cy add if (DEBUG) { Slog.d(TAG, "Processing new values: " + "info=" + mHealthInfo + ", mBatteryLevelCritical=" + mBatteryLevelCritical + ", mPlugType=" + mPlugType); } ... ... } } |
\kernel-4.19-lc\drivers\misc\mediatek\include\mt-plat\battery_common.h
1 2 3 4 5 6 7 | #define BATTERY_CAPACITY_CONTROL //Isaac add typedef struct { ... ... #ifdef BATTERY_CAPACITY_CONTROL int battery_capacity_ctrl; //Isaac add #endif } PMU_ChargerStruct; |
\kernel-4.19-lc\drivers\power\supply\mediatek\battery_common.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | void do_chrdet_int_task(void) { if (g_bat_init_flag == KAL_TRUE) { if (upmu_is_chr_det() == KAL_TRUE) { ... ... } else { ... ... } #ifdef BATTERY_CAPACITY_CONTROL //do_chrdet_int_task()->mt_battery_update_status()->battery_update(), it will set bat_data->BAT_STATUS = POWER_SUPPLY_STATUS_CHARGING //at the same time, skip_battery_update = KAL_TRUE; will skip BAT_thread()->mt_battery_update_status() //So we must reset BMT_status.bat_charging_state here according to BMT_status.battery_capacity_ctrl if (BMT_status.battery_capacity_ctrl) { BMT_status.bat_charging_state = CHR_ERROR; //bat_data->BAT_STATUS = POWER_SUPPLY_STATUS_DISCHARGING } #endif
if (BMT_status.bat_vol > 0) { mt_battery_update_status(); skip_battery_update = KAL_TRUE;
} wake_up_bat(); } else { battery_log(BAT_LOG_CRTI, "[do_chrdet_int_task] battery thread not ready, will do after bettery init.\n"); } } |
\kernel-4.19-lc\drivers\power\supply\mediatek\battery_common.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | void BAT_thread(void) { static kal_bool battery_meter_initilized = KAL_FALSE;
if (battery_meter_initilized == KAL_FALSE) { ... ... }
mt_battery_charger_detect_check(); //CHR_PRE mt_battery_GetBatteryData(); //BMT_status.temperature、charger_vol、bat_vol if (BMT_status.charger_exist == KAL_TRUE) check_battery_exist();
mt_battery_thermal_check(); mt_battery_notify_check();
if ((BMT_status.charger_exist == KAL_TRUE) && (battery_suspended == KAL_FALSE)) { mt_battery_CheckBatteryStatus(); //CHR_PRE #ifdef BATTERY_CAPACITY_CONTROL //do_chrdet_int_task()->mt_battery_charger_detect_check() plug out:set CHR_PRE //BAT_thread()->mt_battery_charger_detect_check() plug out:set CHR_PRE //mt_battery_CheckBatteryStatus()->mt_battery_CheckBatteryTemp()->do_batt_temp_state_machine() low_temp/high_temp recharge:set CHR_PRE //So we must reset BMT_status.bat_charging_state here according to BMT_status.battery_capacity_ctrl if (BMT_status.battery_capacity_ctrl) { BMT_status.bat_charging_state = CHR_ERROR; } #endif mt_battery_charging_algorithm(); }
mt_battery_update_status(); mt_kpoc_power_off_check(); } |
\kernel-4.19-lc\drivers\power\supply\mediatek\battery_common.c
1 2 3 4 5 6 7 | static int battery_probe(struct platform_device *dev) { ... ... #ifdef BATTERY_CAPACITY_CONTROL //Isaac add BMT_status.battery_capacity_ctrl = 0; #endif } |
\kernel-4.19-lc\drivers\power\supply\mediatek\battery_common.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | /* / */ /* BATTERY_CAPACITY_CONTROL API by Isaac add */ /* /sys/devices/platform/mt-battery/BatteryCapacityCtrl */ /* / */ #ifdef BATTERY_CAPACITY_CONTROL static ssize_t show_Battery_Capacity_Ctrl(struct device *dev, struct device_attribute *attr, char *buf) { battery_log(BAT_LOG_CRTI, "Isaac [show_Battery_Capacity_Ctrl] battery_capacity_ctrl : %d\n", BMT_status.battery_capacity_ctrl); return sprintf(buf, "%d\n", BMT_status.battery_capacity_ctrl); }
static ssize_t store_Battery_Capacity_Ctrl(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) { //unsigned int charging_enable = false; if (!kstrtoint(buf, 0, &BMT_status.battery_capacity_ctrl)) { if (BMT_status.battery_capacity_ctrl){ /* Disable charger */ BMT_status.bat_charging_state = CHR_ERROR; //charging_enable = KAL_FALSE; //battery_charging_control(CHARGING_CMD_ENABLE, &charging_enable); wake_up_bat(); } else { BMT_status.bat_charging_state = CHR_PRE; if (BMT_status.charger_exist == KAL_TRUE) { //BMT_status.bat_charging_state = CHR_CC; wake_up_bat(); } } battery_log(BAT_LOG_CRTI, "Isaac [store_Battery_Capacity_Ctrl] battery_capacity_ctrl: %d\n", BMT_status.battery_capacity_ctrl); } else { battery_log(BAT_LOG_CRTI, "Isaac [store_Battery_Capacity_Ctrl] format error!\n"); } return size; }
static DEVICE_ATTR(BatteryCapacityCtrl, 0664, show_Battery_Capacity_Ctrl, store_Battery_Capacity_Ctrl); #endif |
\kernel-4.19-lc\drivers\power\supply\mediatek\battery_common.c
1 2 3 4 5 6 7 | static int mt_batteryNotify_probe(struct platform_device *dev) { ... ... #ifdef BATTERY_CAPACITY_CONTROL ret_device_file = device_create_file(&(dev->dev), &dev_attr_BatteryCapacityCtrl); #endif } |
./sys/devices/platform/mt-battery
./sys/bus/platform/devices/mt-battery
BN_TestMode BatteryNotify driver_override of_node subsystem
BatteryCapacityCtrl driver modalias power uevent
127|tb8321p3_bsp:/sys/bus/platform/devices/mt-battery # cat uevent
DRIVER=mt-battery
OF_NAME=BAT_NOTIFY
OF_FULLNAME=/bus/BAT_NOTIFY
OF_COMPATIBLE_0=mediatek,bat_notify
OF_COMPATIBLE_N=1
MODALIAS=of:NBAT_NOTIFYT<NULL>Cmediatek,bat_notify
./sys/bus/platform/drivers/mt-battery
bind mt-battery uevent unbind //drivers下面也保存着device节点
tb8321p3_bsp:/sys/bus/platform/drivers/mt-battery # cat uevent
cat: uevent: Permission denied
============================================================
解决selinux权限问题:
01-15 14:04:55.775987 775 1309 D cy_batteryservice: batteryLevel=71
01-15 14:04:55.776949 775 1309 D cy_batteryservice: oldChargeModeLimit=60, chargeModeLimit=100
01-15 14:04:55.777242 775 1309 D cy_batteryservice: charge mode changed
01-15 14:04:55.783358 775 1309 D cy_batteryservice: FileNotFoundException
01-15 14:04:55.783997 775 1309 W System.err: java.io.FileNotFoundException: /sys/devices/platform/mt-battery/BatteryCapacityCtrl: open failed: EACCES (Permission denied)
01-15 14:04:55.784710 775 1309 W System.err: at libcore.io.IoBridge.open(IoBridge.java:492)
01-15 14:04:55.785169 775 1309 W System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:236)
01-15 14:04:55.785520 775 1309 W System.err: at java.io.FileOutputStream.<init>(FileOutputStream.java:125)
01-15 14:04:55.785935 775 1309 W System.err: at java.io.FileWriter.<init>(FileWriter.java:63)
01-15 14:04:55.786593 775 1309 W System.err: at com.android.server.BatteryService.fileWrite(BatteryService.java:485)
01-15 14:04:55.787373 775 1309 W System.err: at com.android.server.BatteryService.processValuesLocked(BatteryService.java:526)
01-15 14:04:55.801425 775 1309 W System.err: at com.android.server.BatteryService.update(BatteryService.java:445)
01-15 14:04:55.802217 775 1309 W System.err: at com.android.server.BatteryService.access$1100(BatteryService.java:122)
01-15 14:04:55.805731 775 1309 W System.err: at com.android.server.BatteryService$HealthHalCallback.healthInfoChanged_2_1(BatteryService.java:1197)
01-15 14:04:55.806749 775 1309 W System.err: at android.hardware.health.V2_1.IHealthInfoCallback$Stub.onTransact(IHealthInfoCallback.java:558)
01-15 14:04:55.815422 775 1309 W System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
01-15 14:04:55.816357 775 1309 W System.err: at libcore.io.Linux.open(Native Method)
01-15 14:04:55.821533 775 1309 W System.err: at libcore.io.ForwardingOs.open(ForwardingOs.java:166)
01-15 14:04:55.822753 775 1309 W System.err: at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254)
01-15 14:04:55.823738 775 1309 W System.err: at libcore.io.IoBridge.open(IoBridge.java:478)
01-15 14:04:55.824512 775 1309 W System.err: ... 9 more
<36>[ 505.555309] .(1)[223:logd.auditd]type=1400 audit(1642296439.623:485): avc: denied { read } for comm="cat" name="BatteryCapacityCtrl" dev="sysfs" ino=23191 scontext=u:r:shell:s0 tcontext=u:object_r:sysfs_capacity_ctrl:s0 tclass=file permissive=0
<36>[ 657.526451] .(0)[223:logd.auditd]type=1400 audit(1642296591.588:498): avc: denied { write } for comm="HwBinder:795_5" name="BatteryCapacityCtrl" dev="sysfs" ino=23191 scontext=u:r:system_server:s0 tcontext=u:object_r:sysfs_capacity_ctrl:s0 tclass=file permissive=0
每次开机需要给BMT_status.battery_capacity_ctrl初始化写入一个值:
(220118_09:00:15.403)[ 33.879298] <0>.(0)[774:system_server]BOOTPROF: 33879.275926:AMS:systemReady
(220118_09:00:15.405)[ 33.908790] <0>.(0)[774:system_server]BOOTPROF: 33908.767619:AMS:AMS_READY
(220118_09:00:15.482)[ 33.973157] <0>.(0)[774:system_server]Isaac [store_Battery_Capacity_Ctrl] battery_capacity_ctrl: 0
(220118_09:00:15.486)[ 34.010822] <1>.(1)[774:system_server][MTK-BT]bt_dbg_write: g_bt_turn_on[0], dbg_enable[0], len[19], data = 4w2T8M65K5?2af+a ON
(220118_09:00:15.486)[ 34.012831] <1>.(1)[774:system_server][MTK-BT]bt_dbg_write: g_bt_turn_on[0], dbg_enable[1], len[14], data = 0x12 0x00 0x00
(220118_09:00:15.486)[ 34.014212] <1>.(1)[774:system_server][MTK-BT]bt_dbg_write: y = 0x00000000
(220118_09:00:15.486)[ 34.015065] <1>.(1)[774:system_server][MTK-BT]bt_dbg_write: x(0x00000012), y(0x00000000), z(0x00000000)
(220118_09:00:15.486)[ 34.016272] <1>.(1)[774:system_server][MTK-BT]bt_dbg_write: command id(0x00000012) no handler defined!
(220118_09:00:16.044)[ 34.554620] <3>.(3)[774:system_server]BOOTPROF: 34554.600159:Keyguard bindService
(220118_09:00:16.044)[ 34.560982] <3>.(3)[774:system_server]BOOTPROF: 34560.961851:Keyguard started
(220118_09:00:16.123)[ 34.641879] <0>.(0)[774:system_server]alarm_dev: alarm 3 set 34.609000000
(220118_09:00:16.202)[ 34.679710] <3>.(3)[774:system_server]BOOTPROF: 34679.687544:SystemServer:NetworkStatsService systemReady
(220118_09:00:16.295)[ 34.761269] <3>.(3)[774:system_server]BOOTPROF: 34761.245467:SystemServer:ConnectivityService systemReady
(220118_09:00:16.560)[ 35.086622] <3>.(3)[774:system_server]BOOTPROF: 35086.599621:SystemServer:NetworkPolicyManagerServ systemReady
(220118_09:00:17.234)[ 35.748789] <3>.(3)[774:system_server]BOOTPROF: 35748.765085:SystemServer:PhaseThirdPartyAppsCanStart
(220118_09:00:17.986)[ 36.470049] <2>.(2)[774:system_server]BOOTPROF: 36470.026625:Android:SysServerInit_END
============================================================
最终selinux的权限为:
\device\mediatek\sepolicy\basic\non_plat\file_contexts
/sys/devices/platform/mt-battery/BatteryCapacityCtrl u:object_r:sysfs_capacity_ctrl:s0
\device\mediatek\sepolicy\basic\non_plat\file.te
type sysfs_capacity_ctrl, fs_type, sysfs_type;
\device\mediatek\sepolicy\basic\non_plat\system_app.te
allow system_app sysfs_capacity_ctrl:dir search;
allow system_app sysfs_capacity_ctrl:file rw_file_perms;
\device\mediatek\sepolicy\basic\non_plat\system_server.te
allow system_server sysfs_capacity_ctrl:dir search;
allow system_server sysfs_capacity_ctrl:file rw_file_perms;
\device\mediatek\mt6580\init.mt6580.rc
chmod 0666 /sys/devices/platform/mt-battery/BatteryCapacityCtrl
chown system system /sys/devices/platform/mt-battery/BatteryCapacityCtrl
=====================以下为sysfs_leds/sysfs_vibrator参考代码========================
/device/mediatek/sepolicy/basic/non_plat/genfs_contexts
genfscon sysfs /devices/platform/soc/soc:pwm_leds/leds/lcd-backlight u:object_r:sysfs_leds:s0
/system/sepolicy/private/genfs_contexts
genfscon sysfs /devices/virtual/timed_output/vibrator/enable u:object_r:sysfs_vibrator:s0
=================================================
device_register->device_add()会在/sys目录对应设备目录下创建uevent属性节点
用户态的后台程序(udev)会动态地周期性的扫描/sys目录中的属性项来自动管理设备文件(也称为设备节点),从而在/dev目录会建立或者删除对应的设备文件
./dev/MAINAF
./sys/class/actuatordrv_main_af/MAINAF //模块安装之后会在此目录生成节点, 这里是软链接
./sys/devices/virtual/actuatordrv_main_af/MAINAF //这里是真实的文件节点
./sys/bus/i2c/drivers/MAINAF //i2c_add_driver(&AF_i2c_driver)在i2c-bus上注册驱动,该函数执行成功后会在/sys/bus/i2c/drivers目录下创建.driver.name = AF_DRVNAME为名字的目录。
==============================
/system/sepolicy/prebuilts/api/26.0/private/file_contexts
/sys/class/leds(/.*)? u:object_r:sysfs_leds:s0
/device/mediatek/sepolicy/basic/non_plat/genfs_contexts
genfscon sysfs /devices/platform/leds-mt65xx/leds u:object_r:sysfs_leds:s0
/system/sepolicy/prebuilts/api/30.0/private/genfs_contexts
genfscon sysfs /class/leds u:object_r:sysfs_leds:s0
/system/sepolicy/prebuilts/api/30.0/public/file.te
type sysfs_leds, fs_type, sysfs_type;
/device/mediatek/mt6580/init.mt6580.rc
chown system system /sys/class/leds/lcd-backlight/brightness
chown system system /sys/class/leds/red/brightness
chown system system /sys/class/leds/green/brightness
chmod 0664 /sys/class/leds/lcd-backlight/brightness
chown system system /sys/class/leds/lcd-backlight/brightness
chmod 0664 /sys/class/leds/red/brightness
chown system system /sys/class/leds/red/brightness
chmod 0664 /sys/class/leds/green/brightness
chown system system /sys/class/leds/green/brightness
chmod 0664 /sys/class/leds/blue/brightness
chown system system /sys/class/leds/blue/brightness
/system/sepolicy/private/system_server.te
allow system_server sysfs_vibrator:file { write append };
/device/mediatek/sepolicy/basic/non_plat/mtk_hal_light.te
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # ============================================================================== # Type Declaration # ============================================================================== type mtk_hal_light, domain; type mtk_hal_light_exec, exec_type, file_type, vendor_file_type;
# hwbinder access init_daemon_domain(mtk_hal_light) hwbinder_use(mtk_hal_light)
# call into system_server process (callbacks) binder_call(mtk_hal_light, system_server)
# system file allow mtk_hal_light system_file:dir read; allow mtk_hal_light system_file:dir open;
allow mtk_hal_light sysfs_leds:lnk_file read; allow mtk_hal_light sysfs_leds:file rw_file_perms; allow mtk_hal_light sysfs_leds:dir r_dir_perms;
get_prop(mtk_hal_light, hwservicemanager_prop) hal_server_domain(mtk_hal_light,hal_light); |
/device/mediatek/sepolicy/basic/non_plat/hal_vibrator.te
1 2 3 4 5 6 7 | # vibrator sysfs rw access allow hal_vibrator sysfs_vibrator:dir r_dir_perms; allow hal_vibrator sysfs_leds:file rw_file_perms; allow hal_vibrator sysfs_leds:dir r_dir_perms; allow hal_vibrator sysfs_leds:lnk_file read; allow hal_vibrator sysfs_vibrator:file rw_file_perms; allow hal_vibrator_default sysfs_vibrator:file rw_file_perms; |
./sys/devices/platform/odm/odm:vibrator@0/leds/vibrator/brightness
./sys/devices/platform/leds-mt65xx/leds/lcd-backlight/brightness
tb8321p3_bsp:/sys/class/leds/lcd-backlight # ls
brightness device max_brightness power subsystem trigger uevent
================================================================