BatteryCapacityCtrl电量控制

在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

================================================================

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值