万维网游活动资讯门户

Android-MTK平台功能需求解决:客户电池NTC功能(高低温报警功能)--第1天分析与解决
2025-10-09 04:33:53

MTK平台BUG解决:客户电池NTC功能

一、概述二、步骤1:实现目的?2:准备工作:机制原理的学习(1)MTK充电温度保护机制(2)MTKthermal高温充电机制

3:定位查找与源码分析(1)根据充电温度保护机制kernel层:(2)顺而在与(1)***同目录下的mtk_charger.h***文件中(3)根据充电温度保护机制frameworks层发送广播:(4)根据充电温度保护机制app层接收广播文件:

4:源码详细分析(可暂时跳过)(1)BatteryWarningReceiver.java(2)BatteryWarningActivity.java(3)ThermalWarningActivity(4)batterywarning.cpp

5:目标功能实现推理与复盘6:提出对应解决方案7:解决实现(1) 代码修改-(2) 检查代码-(3) 编译代码:(4) 打包代码(5) 测试:

一、概述

首先我也是第一次收到这个类型的BUG任务,作为Android开发初学者分享一下解决BUG实现相关内容的完整且详细的解决步骤,首先搞清楚问题是什么,目的要干嘛?然后需要做什么准备,有一个大致的定位思路,其次遇到问题思考问题,注意逻辑性、连贯性,再者保持记录与分析,最后得出结果后倒推实现逻辑与复盘,最最后修改代码、检查代码、编译、打包、测试。

二、步骤

1:实现目的?

BUG中描述需要研发人员安排研发移植高低温报警,关机报警功能,具体表现为: 手机充电过程中,

手机温度达47度时,需要将手机充电电流降低到800毫安手机温度达60度时,需要有提示语来提示手机温度过高并停止充电手机温度达65度时,需要有提示语来提示手机温度过高并手机关机 而需要我去修改的主要是2,3点 对此,需要思考电池NTC报警机制和温升控制机制在哪里实现,机制原理是什么? 进而首先要学习机制原理,然后定位电量预警控制相关源码文件内容,分析源码,串联逻辑。

2:准备工作:机制原理的学习

(1)MTK充电温度保护机制

kernel层充电温度保护机制:kernel\kernel-5.15\drivers\power\supply目录下的mtk_charger.c中编写了充电保护线程内容frameworks层发送广播vendor/mediatek/proprietary/frameworks/opt/batterywarning/batterywarning.cppapp层接收广播vendor/mediatek/proprietary/packages/apps/BatteryWarning/src/com/mediatek/batterywarning/BatteryWarningReceiver.java中onCreate()方法判断当mType类型在0-5之间,就调用showWarningDialog()弹出提醒框

(2)MTKthermal高温充电机制

thermal主要由thermal配置文件和thermal的驱动代码进行控制(我描述的简略,更多另外查询)

3:定位查找与源码分析

(1)根据充电温度保护机制kernel层:

kernel\kernel-5.15\drivers\power\supply\mtk_charger.c文件中, 浏览检索到关键词MAX_CHARGE_TEMP,即最高充电温度,

(2)顺而在与(1)同目录下的mtk_charger.h文件中

找到了关键词的自定义值为50,推理此时手机充电电池温度达到50度即发出报警提示与其他操作。

(3)根据充电温度保护机制frameworks层发送广播:

vendor/mediatek/proprietary/frameworks/opt/batterywarning/batterywarning.cpp文件中, batterywarning.cpp中有一个readType方法里有一个条件判断语句,如下图,会根据type的值来输出不同的日志信息并发送广播,由下,又定位到接收广播的文件: app层接收广播的文件路径: \vendor\mediatek\proprietary\packages\apps\BatteryWarning\src\com\mediatek\batterywarning\BatteryWarningActivity.java 这个文件中可以看到有type含义类型: 由此可知当BATTERY_OVER_TEMPERATURE_TYPE = 1即为电池温度过高,所以 需要知道相关方法中条件句中判断type值为1时会执行哪些操作。 在***\frameworks\base\services\core\java\com\android\server\BatteryService.java文件中有个shutdownIfOverTempLocked方法*, 如下: 这个方法意思是如果温度过高就关机,注释中也描述了当温度过高大于68摄氏度时关机, 其中判断语句中的mShutdownBatteryTemperature为默认关机电池温度, 在本文件中搜索关键词mShutdownBatteryTemperature定位到: 可知mShutdownBatteryTemperature取值于名为config_shutdownBatteryTemperature的整型变量,即默认配置关机电池温度, 在终端中使用grep命令搜索config_shutdownBatteryTemperature关键词出现在 \frameworks\base\core\res\res\values\config.xml配置文件中,config.xml文件中config_shutdownBatteryTemperature如下图:

(4)根据充电温度保护机制app层接收广播文件:

vendor/mediatek/proprietary/packages/apps/BatteryWarning/src/com/mediatek/batterywarning/BatteryWarningReceiver.java 在BatteryWarningReceiver.java中分析可知该Java代码主要涉及启动BatteryWarningActivity和ThermalWarningActivity。 BatteryWarningActivity和ThermalWarningActivity的文件路径分别在:

vendor\mediatek\proprietary\packages\apps\BatteryWarning\src\com\mediatek\batterywarning\BatteryWarningActivity.java 用于在电池电量过低时提醒用户vendor\mediatek\proprietary\packages\apps\BatteryWarning\src\com\mediatek\batterywarning\ThermalWarningActivity.java 用于在设备过热时提醒用户。 另外,BatteryWarningReceiver.java中还有一些其他操作,如清除SharedPreferences数据等。 BatteryWarningActivity.java在上一步已经分析,打开其同目录下的ThermalWarningActivity.java进行分析, ThermalWarningActivity.java整段代码的功能: 在温度过高时显示一个警告对话框,并提供一个确定按钮供用户关闭对话框。具体实现是在onCreate方法中获取传递过来的type值,并调用showWarningDialog方法设置对话框的文本信息和按钮监听器。showWarningDialog方法中根据传递过来的type值设置对话框中的文本信息和按钮监听器。当用户点击按钮时,调用finish方法关闭当前Activity。

4:源码详细分析(可暂时跳过)

我主要详细分析下面4份代码:(这一部分内容繁多,可跳过,不理解再查阅)

(1)BatteryWarningReceiver.java

源码如下:

package com.mediatek.batterywarning;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.SharedPreferences;

import android.util.Log;

public class BatteryWarningReceiver extends BroadcastReceiver {

// private static final String ACTION_IPO_BOOT = "android.intent.action.ACTION_BOOT_IPO";

private static final String ACTION_BATTERY_WARNING = "mediatek.intent.action.BATTERY_WARNING";

private static final String ACTION_BATTERY_NORMAL = "mediatek.intent.action.BATTERY_NORMAL";

private static final String TAG = "BatteryWarningReceiver";

private static final String SHARED_PREFERENCES_NAME = "battery_warning_settings";

private Context mContext;

private Context mDeviceContext;

// Thermal over temperature

private static final String ACTION_THERMAL_WARNING = "mediatek.intent.action.THERMAL_DIAG";

@Override

public void onReceive(Context context, Intent intent) {

mContext = context;

mDeviceContext = mContext.createDeviceProtectedStorageContext();

if (mDeviceContext == null) {

mDeviceContext = mContext;

}

String action = intent.getAction();

Log.d(TAG, "action = " + action);

if (Intent.ACTION_BOOT_COMPLETED.equals(action)) {

Log.d(TAG, action + " clear battery_warning_settings shared preference");

SharedPreferences.Editor editor = getSharedPreferences().edit();

editor.clear();

editor.apply();

} else if (ACTION_BATTERY_WARNING.equals(action)) {

Log.d(TAG, action + " start activity according to shared preference");

int type = intent.getIntExtra("type", -1);

Log.d(TAG, "type = " + type);

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

if (type < 0 || type >= BatteryWarningActivity.sWarningTitle.length) {

return;

}

boolean showDialogFlag = getSharedPreferences().getBoolean(

Integer.toString(type), true);

Log.d(TAG, "type = " + type + "showDialogFlag = " + showDialogFlag);

if (showDialogFlag) {

Intent activityIntent = new Intent();

activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK

| Intent.FLAG_ACTIVITY_CLEAR_TOP

| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

activityIntent.setClass(mContext, BatteryWarningActivity.class);

activityIntent.putExtra(BatteryWarningActivity.KEY_TYPE, type);

mContext.startActivity(activityIntent);

}

} else if (ACTION_THERMAL_WARNING.equals(action)) {

int typeValue = intent.getIntExtra(ThermalWarningActivity.KEY_TYPE, -1);

Log.d(TAG, "typeValue = " + typeValue);

if (typeValue == 0 || typeValue == 1) {

Intent thermalIntent = new Intent();

thermalIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK

| Intent.FLAG_ACTIVITY_CLEAR_TOP

| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

thermalIntent.setClass(mContext, ThermalWarningActivity.class);

thermalIntent.putExtra(ThermalWarningActivity.KEY_TYPE, typeValue);

mContext.startActivity(thermalIntent);

}

} else if (ACTION_BATTERY_NORMAL.equals(action)) {

int type = intent.getIntExtra("type", -1);

int type1;

if(type==0)

{

type1=-1;

Intent activityIntent = new Intent();

activityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK

| Intent.FLAG_ACTIVITY_CLEAR_TOP

| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

activityIntent.setClass(mContext, BatteryWarningActivity.class);

activityIntent.putExtra(BatteryWarningActivity.KEY_TYPE, type1);

mContext.startActivity(activityIntent);

}

}

}

private SharedPreferences getSharedPreferences() {

return mDeviceContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);

}

}

代码大体分析: 定义BatteryWarningReceiver类,继承BroadcastReceiver类 定义ACTION_BATTERY_WARNING字符串常量 定义ACTION_BATTERY_NORMAL字符串常量 定义TAG字符串常量,用于日志输出 定义SHARED_PREFERENCES_NAME字符串常量,用于SharedPreferences的名称 定义mContext和mDeviceContext变量,分别表示应用的上下文和设备受保护存储区的上下文 定义ACTION_THERMAL_WARNING字符串常量 定义onReceive方法,用于接收广播并处理相应逻辑 将context赋值给mContext,并通过createDeviceProtectedStorageContext方法创建mDeviceContext 如果mDeviceContext为空,则将mContext赋值给mDeviceContext 获取广播的Action 如果广播的Action是ACTION_BOOT_COMPLETED,则清除SharedPreferences中的battery_warning_settings数据 如果广播的Action是ACTION_BATTERY_WARNING,则根据SharedPreferences中的设置,启动BatteryWarningActivity 如果广播的Action是ACTION_THERMAL_WARNING,则根据传递的参数,启动ThermalWarningActivity 如果广播的Action是ACTION_BATTERY_NORMAL,则根据传递的参数,启动BatteryWarningActivity 定义getSharedPreferences方法,用于获取SharedPreferences对象 整段代码的功能是:接收广播并根据广播的Action执行相应的操作,主要涉及启动BatteryWarningActivity和ThermalWarningActivity。 其中,BatteryWarningActivity用于在电池电量过低时提醒用户, ThermalWarningActivity用于在设备过热时提醒用户。 另外,还有一些其他操作,如清除SharedPreferences数据等。

(2)BatteryWarningActivity.java

源码如下:

package com.mediatek.batterywarning;

import android.app.Activity;

import android.content.BroadcastReceiver;

import android.content.Context;

import android.content.Intent;

import android.content.IntentFilter;

import android.content.SharedPreferences;

import android.media.AudioManager;

import android.media.Ringtone;

import android.media.RingtoneManager;

import android.net.Uri;

import android.os.Bundle;

import android.util.Log;

import android.view.View.OnClickListener;

import android.view.View;

import android.view.Window;

import android.widget.Button;

import android.widget.LinearLayout;

import android.widget.ImageView;

import android.widget.TextView;

import android.app.Notification;

import android.app.NotificationChannel;

import android.app.NotificationManager;

public class BatteryWarningActivity extends Activity {

private static final String TAG = "BatteryWarningActivity";

public static final String WARNING_NOTIFICATION_CHANNEL_ID = "battery_warning_notif_channel";

private static final Uri WARNING_SOUND_URI = Uri

.parse("file:///system/media/audio/ui/VideoRecord.ogg");

private static final String SHARED_PREFERENCES_NAME = "battery_warning_settings";

protected static final String KEY_TYPE = "type";

private static boolean mWaterGas =false;

private Ringtone mRingtone;

private int mType;

private static final int CHARGER_OVER_VOLTAGE_TYPE = 0;

private static final int BATTERY_OVER_TEMPERATURE_TYPE = 1;

private static final int CURRENT_OVER_PROTECTION_TYPE = 2;

private static final int BATTERY_OVER_VOLTAGE_TYPE = 3;

private static final int SAFETY_OVER_TIMEOUT_TYPE = 4;

private static final int BATTERY_LOW_TEMPERATURE_TYPE = 5;

private static final int TYPEC_DETECTION_WATER_GAS_TYPE = 6;

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,

R.string.title_typeC_detection_water_gas

};

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,

R.string.msg_typeC_detection_water_gas };

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) {

Log.d(TAG, "receive ACTION_POWER_DISCONNECTED broadcast, finish");

finish();

}

}

}

};

public static void initWarningNotificationChannel(Context context) {

NotificationManager notificationManager =

(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);

// BatteryWarning Notification Channel

CharSequence name = "Battery Warning";

NotificationChannel mChannelBatWarn = new NotificationChannel(

WARNING_NOTIFICATION_CHANNEL_ID,

name,

NotificationManager.IMPORTANCE_DEFAULT);

notificationManager.createNotificationChannel(mChannelBatWarn);

Log.d(TAG, "initWarningNotificationChannel " + mChannelBatWarn);

}

public static void deleteWarningNotificationChannel(Context context, String channelId) {

Log.d(TAG, "deleteWarningNotificationChannel " + channelId);

NotificationManager notificationManager = (NotificationManager) context.

getSystemService(Context.NOTIFICATION_SERVICE);

notificationManager.deleteNotificationChannel(channelId);

}

public void showBatteryWarningNotification(Context context) {

String title="";

String content="";

title = getString(R.string.notification_title);

content= getString(R.string.notification_wd_text);

NotificationManager notificationManager = (NotificationManager) context.

getSystemService(Context.NOTIFICATION_SERVICE);

Notification notif = new Notification.Builder(context, WARNING_NOTIFICATION_CHANNEL_ID)

.setContentTitle(title)

.setContentText(content)

.setSmallIcon(android.R.drawable.ic_dialog_info)

.setSound(null)

.setOngoing(true)

.build();

notificationManager.notify(0, notif);

}

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);

Context context;

context=BatteryWarningActivity.this;//this.getApplicationContext();

setContentView(R.layout.battery_warning);

getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE,

R.layout.custom_title_1);

Intent intent = getIntent();

mType = intent.getIntExtra(KEY_TYPE, -1);

TextView textView = (TextView) findViewById(R.id.left_text);

Log.d(TAG, "onCreate, mType is " + mType);

if (mType >= CHARGER_OVER_VOLTAGE_TYPE && mType <= TYPEC_DETECTION_WATER_GAS_TYPE) {

textView.setText(getString(sWarningTitle[mType]));

if(mType==TYPEC_DETECTION_WATER_GAS_TYPE)

{

initWarningNotificationChannel(context);

showBatteryWarningNotification(context);

mWaterGas =true;

} else {

deleteWarningNotificationChannel(context,WARNING_NOTIFICATION_CHANNEL_ID);

mWaterGas = false;

}

showWarningDialog(mType);

registerReceiver(mReceiver, new IntentFilter(

Intent.ACTION_POWER_DISCONNECTED));

} else {

if(mWaterGas) {

deleteWarningNotificationChannel(context,WARNING_NOTIFICATION_CHANNEL_ID);

mWaterGas = false;

}

finish();

}

}

protected void onDestroy() {

super.onDestroy();

Log.d(TAG, "onDestroy, stopRingtone");

stopRingtone();

if (mType >= CHARGER_OVER_VOLTAGE_TYPE && mType <= TYPEC_DETECTION_WATER_GAS_TYPE) {

unregisterReceiver(mReceiver);

}

}

private void showWarningDialog(int type) {

TextView textView = (TextView) findViewById(R.id.text);

textView.setText(getString(sWarningMsg[mType]));

LinearLayout layout = (LinearLayout)findViewById(R.id.inner_content);

if(type!= TYPEC_DETECTION_WATER_GAS_TYPE) {

ImageView iv = new ImageView(BatteryWarningActivity.this);

iv.setImageDrawable(getResources().getDrawable(R.drawable.battery_low_battery));

iv.setPadding(4, 4, 4, 4);

layout.addView(iv);

}

Button button = (Button)findViewById(R.id.add);

button.setText(getString(R.string.btn_cancel_msg));

button.setOnClickListener(mDismissContentListener);

button = (Button)findViewById(R.id.remove);

button.setText(getString(R.string.btn_ok_msg));

button.setOnClickListener(mSnoozeContentListener);

playAlertSound(WARNING_SOUND_URI);

}

private OnClickListener mDismissContentListener = new OnClickListener() {

public void onClick(View v) {

stopRingtone();

SharedPreferences.Editor editor = getSharedPreferences().edit();

editor.putBoolean(Integer.toString(mType), false);

editor.apply();

Log.d(TAG, "set type " + mType + " false");

finish();

}

};

private OnClickListener mSnoozeContentListener = new OnClickListener() {

public void onClick(View v) {

stopRingtone();

finish();

}

};

/**

*

* @param context

* The Context that had been passed to

* {@link #warningMessageDialog(Context, Uri)}

* @param defaultUri

*/

private void playAlertSound(Uri defaultUri) {

if (defaultUri != null) {

mRingtone = RingtoneManager.getRingtone(this, defaultUri);

if (mRingtone != null) {

mRingtone.setStreamType(AudioManager.STREAM_SYSTEM);

mRingtone.play();

}

}

}

private void stopRingtone() {

if (mRingtone != null) {

mRingtone.stop();

mRingtone = null;

}

}

private SharedPreferences getSharedPreferences() {

return getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);

}

}

代码大体分析:

这段Java代码是一个Android应用程序中的Activity类,主要实现响应电池异常告警事件的处理。 类的属性定义,主要是定义了一些静态变量,如日志的TAG,告警通知音效的uri,告警通知渠道ID,异常类型等,还有成员变量,如Ringtone实例、Context实例、告警类型等。 定义了一个名为mReceiver的内部广播接收器,主要处理电源断开事件。 静态方法initWarningNotificationChannel,用于在Android系统的通知管理器中创建通知渠道。 静态方法deleteWarningNotificationChannel,用于删除通知渠道。 成员方法showBatteryWarningNotification,用于显示电池告警通知。 该Activity类的onCreate()方法,主要根据接收到的电池异常告警类型展示相应的对话框,还处理了电源断开事件和销毁Activity时的一些操作。 该类的onDestroy()方法,处理Activity销毁后的一些操作,如停止铃声播放和注销广播接收器等。 该类的showWarningDialog方法,显示告警对话框,包括告警类型、告警内容、告警图片和两个按钮(一个取消,一个确定)。 该类的playAlertSound方法,用于播放告警音效。 该类的stopRingtone方法,用于停止告警音效播放。 该类的getSharedPreferences方法,获取应用程序的SharedPreferences对象。 总体来说,该Activity类主要实现了电池异常告警功能,包括通知、动态创建通知渠道、告警对话框的显示和电源断开的处理。

(3)ThermalWarningActivity

源码如下:

package com.mediatek.batterywarning;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.util.Log;

import android.view.View.OnClickListener;

import android.view.View;

import android.view.Window;

import android.widget.Button;

import android.widget.TextView;

/**

* ThermalWarningActivity: show warning dialog when thermal is over temperature.

*/

public class ThermalWarningActivity extends Activity {

private static final String TAG = "ThermalWarningActivity";

protected static final String KEY_TYPE = "type";

private static final int[] sWarningMsg = new int[] { R.string.thermal_clear_temperature,

R.string.thermal_over_temperature };

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

Intent intent = getIntent();

int type = intent.getIntExtra(KEY_TYPE, -1);

Log.d(TAG, "onCreate, type is " + type);

requestWindowFeature(Window.FEATURE_NO_TITLE);

setContentView(R.layout.thermal_warning);

showWarningDialog(type);

}

private void showWarningDialog(int type) {

TextView mMessageView = (TextView) findViewById(R.id.text);

mMessageView.setText(getString(sWarningMsg[type]));

Button button = (Button) findViewById(R.id.yes);

button.setText(getString(android.R.string.yes));

button.setOnClickListener(mYesContentListener);

}

private OnClickListener mYesContentListener = new OnClickListener() {

public void onClick(View v) {

finish();

}

};

}

代码大体分析:

导入需要使用的Android类。 声明一个名为ThermalWarningActivity的类,继承自Activity类。 定义TAG常量和KEY_TYPE常量。 定义一个整型数组sWarningMsg,用于存储两个警告信息的资源ID。 重写onCreate方法,在该方法中获取传递过来的type值,并调用showWarningDialog方法显示警告对话框。 定义showWarningDialog方法,根据传递过来的type值设置对话框中的文本信息和按钮监听器。 定义mYesContentListener匿名内部类,实现OnClickListener接口,当用户点击按钮时调用finish方法关闭当前Activity。 整段代码的功能是:在温度过高时显示一个警告对话框,并提供一个确定按钮供用户关闭对话框。具体实现是在onCreate方法中获取传递过来的type值,并调用showWarningDialog方法设置对话框的文本信息和按钮监听器。showWarningDialog方法中根据传递过来的type值设置对话框中的文本信息和按钮监听器。当用户点击按钮时,调用finish方法关闭当前Activity。

(4)batterywarning.cpp

源码如下:

#define LOG_TAG "batterywarning"

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define MAX_CHAR 100

//M: Currently disabling battery path.. in later stage we will update in code to check path by order. @{

//#ifdef MTK_GM_30

//#define FILE_NAME "/sys/devices/platform/charger/BatteryNotify"

//#else

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

//#endif

//M: @}

#define ACTION "mediatek.intent.action.BATTERY_WARNING"

#define NORMAL_ACTION "mediatek.intent.action.BATTERY_NORMAL"

#define TYPE "type"

#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))

using namespace android;

#define MAX_EPOLL_EVENTS 40

static int uevent_fd;

static int epollfd;

static int eventct;

bool sendBroadcastMessage(String8 action, int value)

{

ALOGD("sendBroadcastMessage(): Action: %s, Value: %d ", (char *)(action.string()), value);

sp sm = defaultServiceManager();

sp am = sm->getService(String16("activity"));

if (am != NULL) {

Parcel data, reply;

data.writeInterfaceToken(String16("android.app.IActivityManager"));

data.writeStrongBinder(NULL);

// Add for match AMS change on O

data.writeInt32(1);

// intent begin

data.writeString8(action); // action

data.writeInt32(0); // URI data type

data.writeString8(NULL, 0); // type

data.writeString8(NULL, 0); // mIdentifier

data.writeInt32(0x04000000); // flags: FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT

data.writeString8(NULL, 0); // package name

data.writeString8(NULL, 0); // component name

data.writeInt32(0); // source bound - size

data.writeInt32(0); // categories - size

data.writeInt32(0); // selector - size

data.writeInt32(0); // clipData - size

data.writeInt32(-2); // contentUserHint: -2 -> UserHandle.USER_CURRENT

data.writeInt32(-1); // bundle extras length

data.writeInt32(0x4C444E42); // 'B' 'N' 'D' 'L'

int oldPos = data.dataPosition();

data.writeInt32(1); // size

// data.writeInt32(0); // VAL_STRING, need to remove because of analyze common intent

data.writeString16(String16(TYPE));

data.writeInt32(1); // VAL_INTEGER

data.writeInt32(value);

int newPos = data.dataPosition();

data.setDataPosition(oldPos - 8);

data.writeInt32(newPos - oldPos); // refill bundle extras length

data.setDataPosition(newPos);

data.writeInt32(0);

// intent end

data.writeString8(NULL, 0); // resolvedType

data.writeStrongBinder(NULL); // resultTo

data.writeInt32(0); // resultCode

data.writeString8(NULL, 0); // resultData

data.writeInt32(-1); // resultExtras

data.writeString8(NULL, 0); // permission

data.writeInt32(0); // appOp

data.writeInt32(-1); // option

data.writeInt32(1); // serialized: != 0 -> ordered

data.writeInt32(0); // sticky

data.writeInt32(-2); // userId: -2 -> UserHandle.USER_CURRENT

status_t ret = am->transact(IBinder::FIRST_CALL_TRANSACTION + 14, data, &reply); // BROADCAST_INTENT_TRANSACTION

if (ret == NO_ERROR) {

int exceptionCode = reply.readExceptionCode();

if (exceptionCode) {

ALOGE("sendBroadcastMessage(%s) caught exception %d\n",

(char *)(action.string()), exceptionCode);

return false;

}

} else {

return false;

}

} else {

ALOGE("getService() couldn't find activity service!\n");

return false;

}

return true;

}

static const char *charger_file_path[] = {

"/sys/devices/platform/charger/BatteryNotify",

"/sys/devices/platform/mt-battery/BatteryNotify",

};

static int read_from_file(const char* path) {

if(!path) {

return 0;

}

int fd =open(path,O_RDONLY);

if(fd<0) {

close(fd);

return 0;

}

else {

close(fd);

return 1;

}

}

int get_charger_file_path() {

int i = 0;

for(i=0;i

if(read_from_file(charger_file_path[i])) {

return i;

}

}

return 0;

}

void readType(char* buffer) {

FILE * pFile;

int file_index;

file_index=get_charger_file_path();

ALOGD("Inside file_index value : %d\n", file_index);

pFile = fopen(charger_file_path[file_index], "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 to remove notification, type = %d\n", type);

sendBroadcastMessage(String8(NORMAL_ACTION), type);

}

if (type > 0)

{

ALOGD("start activity by send intent to BatteryWarningReceiver, type = %d\n", type);

sendBroadcastMessage(String8(ACTION), type);

}

}

#define UEVENT_MSG_LEN 2048

static void uevent_event(uint32_t /*epevents*/) {

char msg[UEVENT_MSG_LEN + 2];

char *cp;

char *status;

int n;

char *buffer = (char*) malloc(MAX_CHAR * sizeof(char));

if (buffer == NULL) {

ALOGD("malloc memory failed");

return ;

}

n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);

if (n <= 0) return;

if (n >= UEVENT_MSG_LEN) /* overflow -- discard */

return;

msg[n] = '\0';

msg[n + 1] = '\0';

cp = msg;

while (*cp) {

if (!strncmp(cp, "CHGSTAT=", strlen("CHGSTAT="))) { // This CHGSTAT value will be provided by kernel driver

readType(buffer);

break;

}

/* advance to after the next \0 */

while (*cp++)

;

}

free(buffer);

}

int batterywarn_register_event(int fd, void (*handler)(uint32_t)) {

struct epoll_event ev;

ev.events = EPOLLIN;

//if (wakeup == EVENT_WAKEUP_FD) ev.events |= EPOLLWAKEUP;

ev.data.ptr = (void*)handler;

if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {

ALOGD("epoll_ctl failed; errno=%d\n", errno);

return -1;

}

return 0;

}

static void uevent_init(void) {

uevent_fd = uevent_open_socket(64 * 1024, true);

if (uevent_fd < 0) {

ALOGD("uevent_init: uevent_open_socket failed\n");

return;

}

fcntl(uevent_fd, F_SETFL, O_NONBLOCK);

if (batterywarn_register_event(uevent_fd, uevent_event))

ALOGD("register for uevent events failed\n");

}

static void batterywarn_mainloop(void) {

int nevents = 0;

while (1) {

struct epoll_event events[1];

nevents = epoll_wait(epollfd, events, 1, -1);

if (nevents == -1) {

if (errno == EINTR) continue;

ALOGD("batterywarn_mainloop: epoll_wait failed\n");

break;

}

for (int n = 0; n < nevents; ++n) {

if (events[n].data.ptr) (*(void (*)(int))events[n].data.ptr)(events[n].events);

}

}

return;

}

static int batterywarn_init() {

epollfd = epoll_create(MAX_EPOLL_EVENTS);

if (epollfd == -1) {

ALOGD("epoll_create failed; errno=%d\n", errno);

return -1;

}

uevent_init();

return 0;

}

int main()

{

char *buffer = (char*) malloc(MAX_CHAR * sizeof(char));

if (buffer == NULL) {

ALOGD("malloc memory failed");

return 0;

}

int ret;

/* Read the status to catch the event when batterywarning is not started */

readType(buffer);

ret= batterywarn_init();

if (ret) {

ALOGD("Initialization failed, exiting\n");

exit(1);

}

batterywarn_mainloop();

free(buffer);

return 0;

}

代码大体分析:

首先sendBroadcastMessage,这是一段用于发送广播消息的代码:定义了一个名为sendBroadcastMessage的函数,它接受两个参数:一个字符串类型的action和一个整型的value,并返回一个布尔类型的值。使用ALOGD函数记录日志,显示传入函数的action和value参数,以便调试和诊断。创建一个sp对象sm并将其初始化为默认服务管理器。使用getService方法从sm中获取一个名为“activity”的服务管理器。判断是否成功获取到了服务管理器am。如果获取到了,就进行下一步操作。如果获取不到则直接返回false。创建一个Parcel对象data,并在其中写入广播消息的不同参数和数据。其中最重要的是在第23-34行里写入了广播的内容值。在这里,action参数被写入到data对象的固定位置,value参数被打包到一个Bundle对象中。这个data对象最终传递给服务管理器am。通过调用am的transact方法向系统发送广播消息并读取回复。在这个过程中,如果出现异常,则捕获并记录错误信息,返回false。如果一切顺利则返回true。 然后定义了一个名为charger_file_path的静态常量字符指针数组, 定义了一个名为read_from_file的静态整型函数, 定义了一个名为get_charger_file_path的整型函数, 然后readType方法里:根据 type 的值进行不同的处理输出日志信息并发送广播。 后面的代码主要包含了对系统电池状态的监控和事件处理的功能

5:目标功能实现推理与复盘

这里不多赘述,主要是通过前面分析的内容去再一步的理清逻辑关系,然后具体分析源码内容以达到更完整的了解

6:提出对应解决方案

此时对温控保护机制温升策略的内容在不同层面已经有了一定了解,已知电池温度type为温度过高时会弹出报警提示及其相关操作,同时知道了mtk_charger.h文件中自定义了最高充电温度,在config.xml配置文件中配置了停机电池温度,针对目的的解决方案为:

①kernel层充电温度保护机制: drivers/power/supply/mediatek/charger/mtk_charger.h中设置了 MAX_CHARGE_TEMP 50,即50度为最高充电温度 将50修改为60。 ②在frameworks\base\core\res\res\values\config.xml配置文件中修改配置停机电池温度: 680默认停机电池温度为68摄氏度, 改为650停机电池温度为65摄氏度。

7:解决实现

(1) 代码修改-

解决方案中已包括

(2) 检查代码-

修改代码完成后保存,在终端使用git status命令查看修改状态

(3) 编译代码:

该MTK_6769平台,先编译A12部分,再编译A13部分,编译成正式软件版本将编译语句中的userdebug改成user。

A13部分:./MSSI_COPY_Make AGN_2263RD_DS12848_T user A12部分:python vendor/mediatek/proprietary/scripts/releasetools/split_build_helper.py –run full_AGN_2263RD_DS12848_T-user --layers vnd 2>&1 |tee total_build1.log

(4) 打包代码

在A13上:

python out_sys/target/product/mssi_64_cn/images/split_build.py --system-dir out_sys/target/product/mssi_64_cn/images --vendor-dir …/S/out/target/product/AGN_2263RD_DS12848_T/images --output-dir output_load

(5) 测试:

由于测试需要特定温度环境等条件,所以发布测试申请让专业的测试人员进行测试。