android高低温报警

         一般来讲手机都会有高低温报警,每个厂商都有自己的不同需求,所以这方面便会有很多定制;而因为平台不同,虽然说殊途同归,实现方式一样,但是代码方面也会有些区别。

         我写java的,所以从java代码入手,讲述一下整个流程。

         1.首先是BatteryWarning这个apk,在kk平台和后面的平台这个apk位置是不一样的,在kk中apk位于alps/mediatek/packages/apps/BatteryWarning,而在后面的平台这个apk则是在alps/vendor/mediatek/proprietary/packages/apps/BatteryWarning。              

         在java代码这一层其实很简单,kk中只有2个类:BatteryWarningActivity.java,BatteryWarningReceiver.java。而后面的平台中也只有3个类:BatteryWarningActivity.java,BatteryWarningReceiver.java,ThermalWarningActivity.java。多出来的ThermalWarningActivity.java是关于手机通信模块过热的,相较于BatteryWarningActivity.java中的警告要轻一些,两者逻辑相同。BatteryWarningActivity.java会受到广播,然后根据广播携带的信息来判断是哪种情况,这其中有一个地方要注意:

type = (int)(Math.log(type) / Math.log(2));

举个例子当传过来的type= 2时,这个是对应温度过高的情况, 经过转换后 type = 1
当传过来的type= 32时,这个是对应温度过低的情况,转换后 type = 5

然后广播通过

activityIntent.putExtra("type", type);
mContext.startActivity(activityIntent);

或者:

                thermalIntent.putExtra(ThermalWarningActivity.KEY_TYPE, typeValue);
                mContext.startActivity(thermalIntent);

将这个值传给BatteryWarningActivity.java或者ThermalWarningActivity.java,接下来不同平台的区别就出来了,kk是没有低温报警的,而之后的平台是有的,kk中我们可以通过如下方式加入低温报警:

	//我加的
    private static final int BATTERY_LOW_TEMPERATURE_TYPE = 5;
    static final int[] sWarningTitle = new int[] {
            R.string.title_charger_over_voltage,
            R.string.title_battery_over_temperature,
            R.string.title_over_current_protection,
            R.string.title_battery_over_voltage,
            R.string.title_safety_timer_timeout,
            //我加的
            R.string.title_battery_low_temperature};
    private static final int[] sWarningMsg = new int[] {
            R.string.msg_charger_over_voltage,
            R.string.msg_battery_over_temperature,
            R.string.msg_over_current_protection,
            R.string.msg_battery_over_voltage,
            R.string.msg_safety_timer_timeout,
            //我加的
            R.string.msg_battery_low_temperature };
	
    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (Intent.ACTION_POWER_DISCONNECTED.equals(action)) {
                if (mType == CHARGER_OVER_VOLTAGE_TYPE
                        || mType == SAFETY_OVER_TIMEOUT_TYPE || mType == BATTERY_LOW_TEMPERATURE_TYPE/*我加的*/) {
                    Xlog.d(TAG, "receive ACTION_POWER_DISCONNECTED broadcast, finish");
                    finish();
                }
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Intent intent = getIntent();
        mType = intent.getIntExtra("type", -1);
        Xlog.d(TAG, "onCreate, mType is " + mType);
        if (mType >= CHARGER_OVER_VOLTAGE_TYPE  && mType <= BATTERY_LOW_TEMPERATURE_TYPE/*我加的*/) {
            showWarningDialog(mType);
            registerReceiver(mReceiver, new IntentFilter(
                    Intent.ACTION_POWER_DISCONNECTED));
        } else {
            finish();
        }
    }
    protected void onDestroy() {
        super.onDestroy();
        if (mType >= CHARGER_OVER_VOLTAGE_TYPE  && mType <= BATTERY_LOW_TEMPERATURE_TYPE/*我加的*/) {
            unregisterReceiver(mReceiver);
        }
    }

代码中有“我加的”注释就是要修改的地方,至于字符串就按照需求放了。

2.说了这么多java代码的,但是有没有发现一个问题,广播哪里发过来的呢?广播多少从java中发过来的,但是这次不一样了,发广播的地方kk中:alps/mediatek/external/batterywarning/batterywarning.c

void readType(char* buffer) {
   FILE * pFile;
    pFile = fopen(FILE_NAME, "r");
    if(pFile == NULL) {
        LOGE("error opening file");
        return;
    } else {
        if(fgets(buffer, MAX_CHAR, pFile) == NULL) {
            LOGE("can not get the string from the file");
            return;
        }
    }
    int type = atoi(buffer);
    if (type > 0 && systemServerStarted(CMD))
    {
        LOGD("start activity by send intent to BatteryWarningReceiver, type = %s", buffer);
        char ps[MAX_LENGTH] = INTENT;
        strcat(ps,buffer);
        LOGD("os.system:  %s", ps);
        system(ps);
    }
    fclose(pFile);
}

其中FILE_NAME:#define FILE_NAME "/sys/devices/platform/mt-battery/BatteryNotify"

INTENT:#define INTENT "am broadcast -n com.mediatek.batterywarning/com.mediatek.batterywarning.BatteryWarningReceiver -a android.intent.action.BATTERY_WARNING --ei type "

在之后的平台则是在:alps/vendor/mediatek/proprietary/frameworks/opt/batterywarning/batterywarning.cpp

void readType(char* buffer) {
    FILE * pFile;
    pFile = fopen(FILE_NAME, "r");
    if (pFile == NULL) {
        ALOGE("error opening file");
        return;
    } else {
        if (fgets(buffer, MAX_CHAR, pFile) == NULL) {
            fclose(pFile);
            ALOGE("can not get the string from the file");
            return;
        }
    }
    fclose(pFile);
    int type = atoi(buffer);
    if (type > 0)
    {
        ALOGD("start activity by send intent to BatteryWarningReceiver, type = %d\n", type);
        sendBroadcastMessage(String16(ACTION), type);
    }
}

FILE_NAME:这个地方和kk就有不同了:

#ifdef MTK_GM_30
#define FILE_NAME "/sys/devices/platform/charger/BatteryNotify"
#else
#define FILE_NAME "/sys/devices/platform/mt-battery/BatteryNotify"

至于怎么判断的呢?可以看alps/kernel-3.18/drivers/power/mediatek/battery_common.c文件(kk平台则是alps/mediatek/kernel/drivers/power/battery_common.c):

struct platform_device MT_batteryNotify_device = {
	.name = "mt-battery",
	.id = -1,
};

那就很明显是mt-battery咯,

ACTION则为:#define ACTION "mediatek.intent.action.BATTERY_WARNING"

可以看的出来后面平台的代码还是要出色的多的。

可以看出具体哪个type和BatteryNotify这个文件有关,那么哪个地方是写这个文件的呢?

这是我们首先要看该文件怎么创建出来的:

static DEVICE_ATTR(BatteryNotify, 0664, show_BatteryNotify, store_BatteryNotify);

这里就是将BatteryNotify文件创建出来的地方,然后我们可以看到里面有show_BatteryNotify这一句,找到这个代码:

static ssize_t show_BatteryNotify(struct device *dev,struct device_attribute *attr, char *buf)
{
    battery_xlog_printk(BAT_LOG_CRTI, "[Battery] show_BatteryNotify : %x\n", g_BatteryNotifyCode);
    
    return sprintf(buf, "%u\n", g_BatteryNotifyCode);
}

哦,原来BatteryNotify里的值是和g_BatteryNotifyCode一样,而在battery_common.c有无数关于g_BatteryNotifyCode的赋值操作,不同情况赋予不同的值,比如温度过高:

    if(BMT_status.temperature >= MAX_CHARGE_TEMPERATURE)
    {
        g_BatteryNotifyCode |= 0x0002;
        battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] bat_temp(%d) out of range(too high)\n", BMT_status.temperature);        
    }

温度过低:

#if defined(MTK_JEITA_STANDARD_SUPPORT)
    else if (BMT_status.temperature < TEMP_NEG_10_THRESHOLD)
    {
        g_BatteryNotifyCode |= 0x0020;
        battery_xlog_printk(BAT_LOG_CRTI, "[BATTERY] bat_temp(%d) out of range(too low)\n", BMT_status.temperature);
    }

那么整个代码流程就已经完毕了,接下来说一个调试技巧。

我们如果要做高温测试的话需要去实验室,来来回回很耽误时间,那么我们调试的时候便可以找到battery_common.c同级目录下的battery_meter.c文件,其中有一个int force_get_tbat(void)方法,将其改成低温报警:

int abcd = 30;//我加的低温报警
int force_get_tbat(void)
{
abcd -= 1;//我加的低温报警
return abcd;//我加的低温报警
#if defined(CONFIG_POWER_EXT) || defined(FIXED_TBAT_25)
	bm_print(BM_LOG_CRTI, "[force_get_tbat] fixed TBAT=25 t\n");
    return 25;

或者高温报警:

int abcd = 30;//我加的低温报警
int force_get_tbat(void)
{
abcd += 1;//我加的低温报警
return abcd;//我加的低温报警
#if defined(CONFIG_POWER_EXT) || defined(FIXED_TBAT_25)
	bm_print(BM_LOG_CRTI, "[force_get_tbat] fixed TBAT=25 t\n");
    return 25;

区别就是自加或者自减,这样的话就可以模拟高低温报警的情况。

 

 

 

你可能感兴趣的:(framework,高低温报警)