BatteryControllerImpl.java

发布时间 2023-06-13 19:56:33作者: 一颗苹果!!
package com.android.systemui.statusbar.policy;

import android.app.ActivityManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.os.BatteryManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
import android.util.Log;
import android.util.Slog;
import com.android.systemui.DemoMode;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
//Added by guanxiubiao for KSSSSZEN-32 20171207 start
import com.xchengtech.ProjectConfig;
import android.os.Vibrator;
//Added by guanxiubiao for KSSSSZEN-32 20171207 end

//xcsw minjiawei battery work mode start
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.ComponentName;
import android.os.BatteryManager;
import com.xchengtech.ProjectConfig;
import android.provider.Settings;
import java.io.BufferedWriter;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.FileReader;
import java.io.IOException;
import android.app.AlarmManager;
import android.app.PendingIntent;
//xcsw minjiawei battery work mode end
//XCSW wenjie.gu add for battery mode start
import android.os.SystemClock;
//XCSW wenjie.gu add for battery mode end


/**
* Default implementation of a {@link BatteryController}. This controller monitors for battery
* level change events that are broadcasted by the system.
*/
public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
private static final String TAG = "BatteryController";

public static final String ACTION_LEVEL_TEST = "com.android.systemui.BATTERY_LEVEL_TEST";

//xcsw minjiawei battery work mode start
private final static String POWER_PATH = "/sys/devices/platform/xc_battery_ctrl/xc_charge_powerpath_en";
private final static String BATTERY_SMARTINFO_PATH = "/sys/devices/platform/xc_battery_ctrl/xc_bat_protect_en";
private final static String VOLTAGE_PATH = "/sys/devices/platform/xc_battery_ctrl/xc_get_vbat";
//xcsw minjiawei battery work mode end

private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);

private final ArrayList<BatteryController.BatteryStateChangeCallback> mChangeCallbacks = new ArrayList<>();
private final PowerManager mPowerManager;
private final Handler mHandler;
private final Context mContext;

protected int mLevel;
protected boolean mPluggedIn;
protected boolean mCharging;
protected boolean mCharged;
protected boolean mPowerSave;
private boolean mTestmode = false;
private boolean mHasReceivedBattery = false;
//Added by guanxiubiao for KSSSSZEN-32 20171207 start
private boolean mVibraFlag=false;
private Vibrator mVibrator=null;
//Added by guanxiubiao for KSSSSZEN-32 20171207 end

//xcsw minjiawei battery work mode start
private int mPlugType;
private static final int DELAY = 72 * 60 * 60 * 1000; // 72 hour
// private static final int DELAY = 24 * 60 * 60 * 1000; // 24 hour
private static final int CHARGEDEBOUNCETIME = 1000 * 60 * 10; // 1 hour //XCSW wenjie.gu modify 60min---> 10min
private static final String ACTION_SCHEDULE_CHANGEMODE = "xcheng.action.schedule.changemode";
private int batteryVolt;
private boolean countChangeLifespan = false;
private boolean countChangeContinuity = false;
private boolean alarmTimeUp = false;
//xcsw minjiawei battery work mode end
//XCSW wenjie.gu add for Start the smart battery after the factory Settings are restored start
private static final int POSITION_FACTORY_RESET_IN_NV = 5;
private static final String XC_CUSTOM_NVRAM_NAME = "/data/nvram/APCFG/APRDEB/XC_CUSTOM";
private static final int RESULT_CLEAR = 43;
private Boolean firstDownload;
//XCSW wenjie.gu add for Start the smart battery after the factory Settings are restored end

public BatteryControllerImpl(Context context) {
mContext = context;
mHandler = new Handler();
mPowerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

registerReceiver();
updatePowerSave();
}

private void registerReceiver() {
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED);
filter.addAction(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING);
filter.addAction(ACTION_LEVEL_TEST);
//xcsw minjiawei battery work mode start
filter.addAction(ACTION_SCHEDULE_CHANGEMODE);
//xcsw minjiawei battery work mode end
mContext.registerReceiver(this, filter);
}

@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("BatteryController state:");
pw.print(" mLevel="); pw.println(mLevel);
pw.print(" mPluggedIn="); pw.println(mPluggedIn);
pw.print(" mCharging="); pw.println(mCharging);
pw.print(" mCharged="); pw.println(mCharged);
pw.print(" mPowerSave="); pw.println(mPowerSave);
}

@Override
public void setPowerSaveMode(boolean powerSave) {
mPowerManager.setPowerSaveMode(powerSave);
}

@Override
public void addStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
synchronized (mChangeCallbacks) {
mChangeCallbacks.add(cb);
}
if (!mHasReceivedBattery) return;
cb.onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
cb.onPowerSaveChanged(mPowerSave);
}

@Override
public void removeStateChangedCallback(BatteryController.BatteryStateChangeCallback cb) {
synchronized (mChangeCallbacks) {
mChangeCallbacks.remove(cb);
}
}

@Override
public void onReceive(final Context context, Intent intent) {
SharedPreferences sp_Num = context.getSharedPreferences("count_preferences", Context.MODE_PRIVATE);
firstDownload =sp_Num.getBoolean("firstimedownload",true);
final String action = intent.getAction();
if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
if (mTestmode && !intent.getBooleanExtra("testmode", false)) return;
mHasReceivedBattery = true;
mLevel = (int)(100f
* intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
/ intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100));
mPluggedIn = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0) != 0;
//xcsw minjiawei battery work mode start
batteryVolt = intent.getIntExtra(BatteryManager.EXTRA_VOLTAGE, -1);
//xcsw minjiawei battery work mode end
final int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
mCharged = status == BatteryManager.BATTERY_STATUS_FULL;
mCharging = mCharged || status == BatteryManager.BATTERY_STATUS_CHARGING;
//Added by guanxiubiao for KSSSSZEN-32 20171207 start
if(mCharging && mPluggedIn && ProjectConfig.XC_VIBRATOR_WHEN_CHARGER){
if(mVibrator==null){
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
}
if(!mVibraFlag){
mVibrator.vibrate(1000);
mVibraFlag=true;
}

}else{
mVibraFlag=false;
}
//Added by guanxiubiao for KSSSSZEN-32 20171207 end
fireBatteryLevelChanged();

//xcsw minjiawei battery work mode start
if (ProjectConfig.FEATURE_BATTERY_WORK_MODE_SUPPORT && !isAgingTestRunning() && getRebootFlag()) {
if (alarmTimeUp) {
try {
int batteryV = Integer.valueOf(read(VOLTAGE_PATH));
checkBatteryVoltage(batteryV);
} catch(Exception e) {
Slog.i(TAG, "read VOLTAGE_PATH Exception:" + e.toString());
}
}
int mBatteryWorkModeValue = Settings.System.getInt(context.getContentResolver(), Settings.Global.BATTERY_WORK_MODE, 0);
final int oldPlugType = mPlugType;
mPlugType = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 1);
Slog.i(TAG, "oldPlugType:" + oldPlugType + " mPlugType:" + mPlugType);
if (mBatteryWorkModeValue == 0) {
if (oldPlugType == 0 && mPlugType != 0) {
BatteryManager manager = (BatteryManager) context.getSystemService(Context.BATTERY_SERVICE);
int mBatteryLevel = getBatteryLevel(mContext);
Slog.i(TAG,"mBatteryLevel --->"+mBatteryLevel);
SharedPreferences sp = context.getSharedPreferences("count_preferences", Context.MODE_PRIVATE);
int chargecount = sp.getInt("chargecount",0);
int highpowercount = sp.getInt("highpowercount",0);
int lowpowercount = sp.getInt("lowpowercount",0);
long chargelasttime = sp.getLong("chargelasttime", 0L);
long nowtime = new Date().getTime();
Slog.i(TAG,"now time ="+getTimeByLong(nowtime));
Slog.i(TAG,"chargelasttime ="+getTimeByLong(chargelasttime));
Slog.i(TAG, "(nowtime - chargelasttime) / CHARGEDEBOUNCETIME before:" + (nowtime - chargelasttime) / CHARGEDEBOUNCETIME);
if (((nowtime - chargelasttime) / CHARGEDEBOUNCETIME >= 1)) {
Slog.i(TAG, "nowtime - chargelasttime >= 1");
Slog.i(TAG,"now time ="+getTimeByLong(nowtime));
Slog.i(TAG,"chargelasttime ="+getTimeByLong(chargelasttime));
int lastChargeLevel =sp.getInt("mbatterylevelold",0);
int nowBatteryLevel = getBatteryLevel(mContext);
Boolean mBTLevelchange = (nowBatteryLevel - lastChargeLevel) >= 2;
if (mBTLevelchange) {
Slog.i(TAG, "nowBatteryLevel --->" + nowBatteryLevel);
Slog.i(TAG, "lastChargeLevel --->" + lastChargeLevel);
Slog.i(TAG, "nowBatteryLevel -lastChargeLevel --->" + (nowBatteryLevel - lastChargeLevel));
if (mBatteryLevel > 50) {
highpowercount = highpowercount + 1;
} else {
lowpowercount = lowpowercount + 1;
}
chargecount = chargecount + 1;
if (chargecount >= 11) {
if (highpowercount == lowpowercount) {
} else if (highpowercount > lowpowercount) {
if (isBatterySmartInfoPathExist()) {
countChangeLifespan = true;
}
} else {
if (isBatterySmartInfoPathExist()) {
countChangeContinuity = true;
}
}
chargecount = 0;
highpowercount = 0;
lowpowercount = 0;
}
Editor editor = sp.edit();
editor.putInt("chargecount", chargecount);
editor.putInt("highpowercount", highpowercount);
editor.putInt("lowpowercount", lowpowercount);
editor.putLong("chargelasttime", nowtime);
editor.putInt("mbatterylevelold",nowBatteryLevel);
editor.commit();
Slog.i(TAG, "chargecount:" + sp.getInt("chargecount", 0));
Slog.i(TAG, "highpowercount:" + sp.getInt("highpowercount", 0));
Slog.i(TAG, "lowpowercount:" + sp.getInt("lowpowercount", 0));
Slog.i(TAG, "mBatteryLevelOld:" + sp.getInt("mbatterylevelold", 0));
}
}
}
if (oldPlugType != 0 && mPlugType == 0) {
if (countChangeLifespan && isBatterySmartInfoPathExist()) {
write(BATTERY_SMARTINFO_PATH, "1");
Settings.System.putInt(mContext.getContentResolver(), Settings.Global.BATTERY_WORK_STATUS, 1);
}
if (countChangeContinuity && isBatterySmartInfoPathExist()) {
write(BATTERY_SMARTINFO_PATH, "0");
Settings.System.putInt(mContext.getContentResolver(), Settings.Global.BATTERY_WORK_STATUS, 0);
}
countChangeContinuity = false;
countChangeLifespan = false;
}
}
if (mBatteryWorkModeValue == 0 || mBatteryWorkModeValue == 1) {
if (oldPlugType == 0 && mPlugType != 0) {
startChangeBatteryModeAlarm();
} else if (oldPlugType != 0 && mPlugType == 0) {
cancelChangeBatteryModeAlarm(context);
}
}
}
if (ProjectConfig.FEATURE_BATTERY_WORK_MODE_SUPPORT && !isAgingTestRunning() && getRebootFlag()) {
if (isBatterySmartInfoPathExist() && firstDownload){
write(BATTERY_SMARTINFO_PATH, "0");
Settings.System.putInt(mContext.getContentResolver(), Settings.Global.BATTERY_WORK_STATUS, 0);
Editor editor_dL = sp_Num.edit();
editor_dL.putBoolean("firstimedownload",false);
editor_dL.commit();
}
}
//xcsw minjiawei battery work mode end
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGED)) {
updatePowerSave();
} else if (action.equals(PowerManager.ACTION_POWER_SAVE_MODE_CHANGING)) {
setPowerSave(intent.getBooleanExtra(PowerManager.EXTRA_POWER_SAVE_MODE, false));
} else if (action.equals(ACTION_LEVEL_TEST)) {
mTestmode = true;
mHandler.post(new Runnable() {
int curLevel = 0;
int incr = 1;
int saveLevel = mLevel;
boolean savePlugged = mPluggedIn;
Intent dummy = new Intent(Intent.ACTION_BATTERY_CHANGED);
@Override
public void run() {
if (curLevel < 0) {
mTestmode = false;
dummy.putExtra("level", saveLevel);
dummy.putExtra("plugged", savePlugged);
dummy.putExtra("testmode", false);
} else {
dummy.putExtra("level", curLevel);
dummy.putExtra("plugged", incr > 0 ? BatteryManager.BATTERY_PLUGGED_AC
: 0);
dummy.putExtra("testmode", true);
}
context.sendBroadcast(dummy);

if (!mTestmode) return;

curLevel += incr;
if (curLevel == 100) {
incr *= -1;
}
mHandler.postDelayed(this, 200);
}
});
} else if (action.equals(ACTION_SCHEDULE_CHANGEMODE)) {
Slog.i(TAG, "batteryVolt:" + batteryVolt);
cancelChangeBatteryModeAlarm(context);
changeBatteryMode(batteryVolt);
resetChargeCount(context);
}
}

@Override
public boolean isPowerSave() {
return mPowerSave;
}

private void updatePowerSave() {
setPowerSave(mPowerManager.isPowerSaveMode());
}

private void setPowerSave(boolean powerSave) {
if (powerSave == mPowerSave) return;
mPowerSave = powerSave;
if (DEBUG) Log.d(TAG, "Power save is " + (mPowerSave ? "on" : "off"));
firePowerSaveChanged();
}

protected void fireBatteryLevelChanged() {
synchronized (mChangeCallbacks) {
final int N = mChangeCallbacks.size();
for (int i = 0; i < N; i++) {
mChangeCallbacks.get(i).onBatteryLevelChanged(mLevel, mPluggedIn, mCharging);
}
}
}

private void firePowerSaveChanged() {
synchronized (mChangeCallbacks) {
final int N = mChangeCallbacks.size();
for (int i = 0; i < N; i++) {
mChangeCallbacks.get(i).onPowerSaveChanged(mPowerSave);
}
}
}

private boolean mDemoMode;

@Override
public void dispatchDemoCommand(String command, Bundle args) {
if (!mDemoMode && command.equals(COMMAND_ENTER)) {
mDemoMode = true;
mContext.unregisterReceiver(this);
} else if (mDemoMode && command.equals(COMMAND_EXIT)) {
mDemoMode = false;
registerReceiver();
updatePowerSave();
} else if (mDemoMode && command.equals(COMMAND_BATTERY)) {
String level = args.getString("level");
String plugged = args.getString("plugged");
if (level != null) {
mLevel = Math.min(Math.max(Integer.parseInt(level), 0), 100);
}
if (plugged != null) {
mPluggedIn = Boolean.parseBoolean(plugged);
}
fireBatteryLevelChanged();
}
}

//xcsw minjiawei battery work mode start
private void write(String path, String value) {
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw = new FileWriter(path);
bw = new BufferedWriter(fw);
String line = value;
bw.write(line);
bw.flush();
bw.close();
fw.close();
Slog.i(TAG, "write path:" + path + " value:" + value);
} catch (IOException e) {
e.printStackTrace();
Slog.e(TAG, "write exception:" + e.toString());
}
}

private String read(String path) {
FileReader fr2 = null;
BufferedReader bufr = null;
StringBuilder stringBuilder = new StringBuilder();
try {
fr2 = new FileReader(path);
bufr = new BufferedReader(fr2);
String line = null;
while((line = bufr.readLine()) != null) {
stringBuilder.append(line);
}
} catch(IOException e) {
e.printStackTrace();
} finally {
try {
if (fr2 != null) {
fr2.close();
}
if (bufr!=null) {
bufr.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return stringBuilder.toString();
}

private boolean isBatterySmartInfoPathExist() {
try {
File file = new File(BATTERY_SMARTINFO_PATH);
if (file.exists()) {
Slog.i(TAG, "isBatterySmartInfoPathExist file exist");
return true;
}
} catch (Exception e) {
e.printStackTrace();
Slog.i(TAG, "isBatterySmartInfoPathExist exception:" + e.toString());
}
Slog.i(TAG, "isBatterySmartInfoPathExist file not exist");
return false;
}

private void startChangeBatteryModeAlarm() {
Slog.i(TAG, "startAlarm");
alarmTimeUp = false;
Intent intent = new Intent(ACTION_SCHEDULE_CHANGEMODE);
PendingIntent sender = PendingIntent.getBroadcast(mContext,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager am = (AlarmManager) mContext
.getSystemService(Context.ALARM_SERVICE);

long changeModeTime = SystemClock.elapsedRealtime() + DELAY;
am.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, changeModeTime, sender);
// Add log when timer is finished
Handler handler = new Handler();
handler.postDelayed(() -> Slog.i(TAG, "Timer finished"), DELAY);
}


public void cancelChangeBatteryModeAlarm(Context context) {
Slog.i(TAG, "cancelAlarm");
Intent intent = new Intent(ACTION_SCHEDULE_CHANGEMODE);
PendingIntent sender = PendingIntent.getBroadcast(context,
0, intent, PendingIntent.FLAG_CANCEL_CURRENT);

AlarmManager am = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);

am.cancel(sender);
}

private void changeBatteryMode(int batteryVolt) {
alarmTimeUp = true;
int mBatteryWorkModeValue = Settings.System.getInt(mContext.getContentResolver(),
Settings.Global.BATTERY_WORK_MODE, 0);
Slog.i(TAG, "changeBatteryMode mBatteryWorkModeValue:" + mBatteryWorkModeValue + " batteryVolt:" + batteryVolt);
if (mBatteryWorkModeValue == 0) {
Slog.i(TAG, "changeBatteryModeRunnable run mBatteryWorkModeValue 0");
if (isBatterySmartInfoPathExist()) {
write(BATTERY_SMARTINFO_PATH, "1");
Settings.System.putInt(mContext.getContentResolver(), Settings.Global.BATTERY_WORK_STATUS, 1);
}
if (batteryVolt > 8400) {
if (isBatterySmartInfoPathExist()) {
write(POWER_PATH, "0");
}
} else {
if (isBatterySmartInfoPathExist()) {
write(POWER_PATH, "1");
}
}
} else if (mBatteryWorkModeValue == 1) {
Slog.i(TAG, "changeBatteryModeRunnable run mBatteryWorkModeValue 1");
Settings.System.putInt(mContext.getContentResolver(), Settings.Global.BATTERY_WORK_MODE, 2);
if (isBatterySmartInfoPathExist()) {
write(BATTERY_SMARTINFO_PATH, "1");
Settings.System.putInt(mContext.getContentResolver(), Settings.Global.BATTERY_WORK_STATUS, 1);
}
if (batteryVolt > 8400) {
if (isBatterySmartInfoPathExist()) {
write(POWER_PATH, "0");
}
} else {
if (isBatterySmartInfoPathExist()) {
write(POWER_PATH, "1");
}
}
}
}

private void checkBatteryVoltage(int batteryVolt) {
int mBatteryWorkModeValue = Settings.System.getInt(mContext.getContentResolver(),
Settings.Global.BATTERY_WORK_MODE, 0);
Slog.i(TAG, "checkBatteryVoltage mBatteryWorkModeValue:" + mBatteryWorkModeValue + " batteryVolt:" + batteryVolt);
if (mBatteryWorkModeValue == 0 || mBatteryWorkModeValue == 1) {
if (batteryVolt <= 8400) {
if (isBatterySmartInfoPathExist()) {
write(POWER_PATH, "1");
}
} else {
if (isBatterySmartInfoPathExist()) {
write(POWER_PATH, "0");
}
}
}
}

private boolean isAgingTestRunning() {
ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(1);
if (runningTasks != null && runningTasks.size() > 0) {
ComponentName comName = runningTasks.get(0).topActivity;
if ("com.xcheng.agingtest".equals(comName.getPackageName())) {
return true;
}
}
return false;
}

public void resetChargeCount(Context context) {
Slog.i(TAG, "resetChargeCount");
SharedPreferences sp = context.getSharedPreferences("count_preferences", Context.MODE_PRIVATE);
Editor editor = sp.edit();
editor.putInt("chargecount", 0);
editor.putInt("highpowercount", 0);
editor.putInt("lowpowercount", 0);
editor.commit();
}
//xcsw minjiawei battery work mode end
//XCSW wenjie.gu add for Start the smart battery after the factory Settings are restored start
public boolean getRebootFlag(){
return NVRAMHelper.isMasterCleared();
}
//XCSW wenjie.gu add for Start the smart battery after the factory Settings are restored end
private String getTimeByLong(Long time){
long timeStamp = time; // 2020-08-22 16:20:08.000
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
String formattedTime = sdf.format(new Date(timeStamp));
return formattedTime;
}
public static int getBatteryLevel(Context context) {
Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
float batteryPct = level * 100 / (float)scale;
return (int)batteryPct;
}
public boolean isSystemApp(Context context) {
PackageManager pm = context.getPackageManager();
String packageName = context.getPackageName();
try {
ApplicationInfo ai = pm.getApplicationInfo(packageName, 0);
return (ai.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return false;
}
}