auto import from //depot/cupcake/@137055
This commit is contained in:
@ -20,20 +20,31 @@ import com.android.internal.app.IBatteryStats;
|
||||
import com.android.server.am.BatteryStatsService;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Debug;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceManager;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UEventObserver;
|
||||
import android.provider.Checkin;
|
||||
import android.provider.Settings;
|
||||
import android.util.EventLog;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.String;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>BatteryService monitors the charging status, and charge level of the device
|
||||
@ -60,12 +71,24 @@ import java.lang.String;
|
||||
class BatteryService extends Binder {
|
||||
private static final String TAG = BatteryService.class.getSimpleName();
|
||||
|
||||
private static final boolean LOCAL_LOGV = false;
|
||||
|
||||
static final int LOG_BATTERY_LEVEL = 2722;
|
||||
static final int LOG_BATTERY_STATUS = 2723;
|
||||
static final int LOG_BATTERY_DISCHARGE_STATUS = 2730;
|
||||
|
||||
static final int BATTERY_SCALE = 100; // battery capacity is a percentage
|
||||
|
||||
// Used locally for determining when to make a last ditch effort to log
|
||||
// discharge stats before the device dies.
|
||||
private static final int CRITICAL_BATTERY_LEVEL = 4;
|
||||
|
||||
private static final int DUMP_MAX_LENGTH = 24 * 1024;
|
||||
private static final String[] DUMPSYS_ARGS = new String[] { "-c", "-u" };
|
||||
private static final String BATTERY_STATS_SERVICE_NAME = "batteryinfo";
|
||||
|
||||
private static final String DUMPSYS_DATA_PATH = "/data/system/";
|
||||
|
||||
// This should probably be exposed in the API, though it's not critical
|
||||
private static final int BATTERY_PLUGGED_NONE = 0;
|
||||
|
||||
@ -81,6 +104,7 @@ class BatteryService extends Binder {
|
||||
private int mBatteryVoltage;
|
||||
private int mBatteryTemperature;
|
||||
private String mBatteryTechnology;
|
||||
private boolean mBatteryLevelCritical;
|
||||
|
||||
private int mLastBatteryStatus;
|
||||
private int mLastBatteryHealth;
|
||||
@ -88,6 +112,7 @@ class BatteryService extends Binder {
|
||||
private int mLastBatteryLevel;
|
||||
private int mLastBatteryVoltage;
|
||||
private int mLastBatteryTemperature;
|
||||
private boolean mLastBatteryLevelCritical;
|
||||
|
||||
private int mPlugType;
|
||||
private int mLastPlugType = -1; // Extra state so we can detect first run
|
||||
@ -95,6 +120,7 @@ class BatteryService extends Binder {
|
||||
private long mDischargeStartTime;
|
||||
private int mDischargeStartLevel;
|
||||
|
||||
|
||||
public BatteryService(Context context) {
|
||||
mContext = context;
|
||||
mBatteryStats = BatteryStatsService.getService();
|
||||
@ -149,6 +175,8 @@ class BatteryService extends Binder {
|
||||
|
||||
private synchronized final void update() {
|
||||
native_update();
|
||||
|
||||
mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL;
|
||||
if (mAcOnline) {
|
||||
mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
|
||||
} else if (mUsbOnline) {
|
||||
@ -176,6 +204,8 @@ class BatteryService extends Binder {
|
||||
mDischargeStartLevel, mBatteryLevel);
|
||||
// make sure we see a discharge event before logging again
|
||||
mDischargeStartTime = 0;
|
||||
|
||||
logOutlier(duration);
|
||||
}
|
||||
} else if (mPlugType == BATTERY_PLUGGED_NONE) {
|
||||
// charging -> discharging or we just powered up
|
||||
@ -197,6 +227,12 @@ class BatteryService extends Binder {
|
||||
EventLog.writeEvent(LOG_BATTERY_LEVEL,
|
||||
mBatteryLevel, mBatteryVoltage, mBatteryTemperature);
|
||||
}
|
||||
if (mBatteryLevelCritical && !mLastBatteryLevelCritical &&
|
||||
mPlugType == BATTERY_PLUGGED_NONE) {
|
||||
// We want to make sure we log discharge cycle outliers
|
||||
// if the battery is about to die.
|
||||
logOutlier(SystemClock.elapsedRealtime() - mDischargeStartTime);
|
||||
}
|
||||
|
||||
mLastBatteryStatus = mBatteryStatus;
|
||||
mLastBatteryHealth = mBatteryHealth;
|
||||
@ -205,6 +241,7 @@ class BatteryService extends Binder {
|
||||
mLastPlugType = mPlugType;
|
||||
mLastBatteryVoltage = mBatteryVoltage;
|
||||
mLastBatteryTemperature = mBatteryTemperature;
|
||||
mLastBatteryLevelCritical = mBatteryLevelCritical;
|
||||
|
||||
sendIntent();
|
||||
}
|
||||
@ -247,6 +284,83 @@ class BatteryService extends Binder {
|
||||
ActivityManagerNative.broadcastStickyIntent(intent, null);
|
||||
}
|
||||
|
||||
private final void logBatteryStats() {
|
||||
|
||||
IBinder batteryInfoService = ServiceManager.getService(BATTERY_STATS_SERVICE_NAME);
|
||||
if (batteryInfoService != null) {
|
||||
byte[] buffer = new byte[DUMP_MAX_LENGTH];
|
||||
File dumpFile = null;
|
||||
FileOutputStream dumpStream = null;
|
||||
try {
|
||||
// dump the service to a file
|
||||
dumpFile = new File(DUMPSYS_DATA_PATH + BATTERY_STATS_SERVICE_NAME + ".dump");
|
||||
dumpStream = new FileOutputStream(dumpFile);
|
||||
batteryInfoService.dump(dumpStream.getFD(), DUMPSYS_ARGS);
|
||||
dumpStream.getFD().sync();
|
||||
|
||||
// read dumped file above into buffer truncated to DUMP_MAX_LENGTH
|
||||
// and insert into events table.
|
||||
int length = (int) Math.min(dumpFile.length(), DUMP_MAX_LENGTH);
|
||||
FileInputStream fileInputStream = new FileInputStream(dumpFile);
|
||||
int nread = fileInputStream.read(buffer, 0, length);
|
||||
if (nread > 0) {
|
||||
Checkin.logEvent(mContext.getContentResolver(),
|
||||
Checkin.Events.Tag.BATTERY_DISCHARGE_INFO,
|
||||
new String(buffer, 0, nread));
|
||||
if (LOCAL_LOGV) Log.v(TAG, "dumped " + nread + "b from " +
|
||||
batteryInfoService + "to log");
|
||||
if (LOCAL_LOGV) Log.v(TAG, "actual dump:" + new String(buffer, 0, nread));
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "failed to dump service '" + BATTERY_STATS_SERVICE_NAME +
|
||||
"':" + e);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "failed to write dumpsys file: " + e);
|
||||
} finally {
|
||||
// make sure we clean up
|
||||
if (dumpStream != null) {
|
||||
try {
|
||||
dumpStream.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "failed to close dumpsys output stream");
|
||||
}
|
||||
}
|
||||
if (dumpFile != null && !dumpFile.delete()) {
|
||||
Log.e(TAG, "failed to delete temporary dumpsys file: "
|
||||
+ dumpFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final void logOutlier(long duration) {
|
||||
ContentResolver cr = mContext.getContentResolver();
|
||||
String dischargeThresholdString = Settings.Gservices.getString(cr,
|
||||
Settings.Gservices.BATTERY_DISCHARGE_THRESHOLD);
|
||||
String durationThresholdString = Settings.Gservices.getString(cr,
|
||||
Settings.Gservices.BATTERY_DISCHARGE_DURATION_THRESHOLD);
|
||||
|
||||
if (dischargeThresholdString != null && durationThresholdString != null) {
|
||||
try {
|
||||
long durationThreshold = Long.parseLong(durationThresholdString);
|
||||
int dischargeThreshold = Integer.parseInt(dischargeThresholdString);
|
||||
if (duration <= durationThreshold &&
|
||||
mDischargeStartLevel - mBatteryLevel >= dischargeThreshold) {
|
||||
// If the discharge cycle is bad enough we want to know about it.
|
||||
logBatteryStats();
|
||||
}
|
||||
if (LOCAL_LOGV) Log.v(TAG, "duration threshold: " + durationThreshold +
|
||||
" discharge threshold: " + dischargeThreshold);
|
||||
if (LOCAL_LOGV) Log.v(TAG, "duration: " + duration + " discharge: " +
|
||||
(mDischargeStartLevel - mBatteryLevel));
|
||||
} catch (NumberFormatException e) {
|
||||
Log.e(TAG, "Invalid DischargeThresholds GService string: " +
|
||||
durationThresholdString + " or " + dischargeThresholdString);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final int getIcon(int level) {
|
||||
if (mBatteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
|
||||
return com.android.internal.R.drawable.stat_sys_battery_charge;
|
||||
|
Reference in New Issue
Block a user