Some battery improvements:

- New API for iterating over history that will allow a better implementation
  in the future.
- Now do writes asynchronously.

Also improve the documentation for Activity.onRetainNonInstanceState().

Change-Id: Idf67f2796a8868eb62f288bcbb2bad29876c8554
This commit is contained in:
Dianne Hackborn
2010-09-20 11:39:14 -07:00
parent 8544560ccc
commit ce2ef766ca
5 changed files with 107 additions and 20 deletions

View File

@@ -1427,7 +1427,9 @@ public class Activity extends ContextThemeWrapper
* <li> The function will be called between {@link #onStop} and
* {@link #onDestroy}.
* <li> A new instance of the activity will <em>always</em> be immediately
* created after this one's {@link #onDestroy()} is called.
* created after this one's {@link #onDestroy()} is called. In particular,
* <em>no</em> messages will be dispatched during this time (when the returned
* object does not have an activity to be associated with).
* <li> The object you return here will <em>always</em> be available from
* the {@link #getLastNonConfigurationInstance()} method of the following
* activity instance as described there.
@@ -1440,6 +1442,15 @@ public class Activity extends ContextThemeWrapper
* may change based on the configuration, including any data loaded from
* resources such as strings, layouts, or drawables.
*
* <p>The guarantee of no message handling during the switch to the next
* activity simplifies use with active objects. For example if your retained
* state is an {@link android.os.AsyncTask} you are guaranteed that its
* call back functions (like {@link android.os.AsyncTask#onPostExecute}) will
* not be called from the call here until you execute the next instance's
* {@link #onCreate(Bundle)}. (Note however that there is of course no such
* guarantee for {@link android.os.AsyncTask#doInBackground} since that is
* running in a separate thread.)
*
* @return Return any Object holding the desired state to propagate to the
* next activity instance.
*/

View File

@@ -397,7 +397,7 @@ public abstract class BatteryStats implements Parcelable {
}
}
public final class HistoryItem implements Parcelable {
public final static class HistoryItem implements Parcelable {
public HistoryItem next;
public long time;
@@ -482,6 +482,18 @@ public abstract class BatteryStats implements Parcelable {
dest.writeInt(states);
}
public void setTo(HistoryItem o) {
time = o.time;
cmd = o.cmd;
batteryLevel = o.batteryLevel;
batteryStatus = o.batteryStatus;
batteryHealth = o.batteryHealth;
batteryPlugType = o.batteryPlugType;
batteryTemperature = o.batteryTemperature;
batteryVoltage = o.batteryVoltage;
states = o.states;
}
public void setTo(long time, byte cmd, HistoryItem o) {
this.time = time;
this.cmd = cmd;
@@ -526,6 +538,10 @@ public abstract class BatteryStats implements Parcelable {
}
}
public abstract boolean startIteratingHistoryLocked();
public abstract boolean getNextHistoryLocked(HistoryItem out);
/**
* Return the current history of battery state changes.
*/
@@ -1688,8 +1704,8 @@ public abstract class BatteryStats implements Parcelable {
*/
@SuppressWarnings("unused")
public void dumpLocked(PrintWriter pw) {
HistoryItem rec = getHistory();
if (rec != null) {
final HistoryItem rec = new HistoryItem();
if (startIteratingHistoryLocked()) {
pw.println("Battery History:");
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
int oldState = 0;
@@ -1698,7 +1714,7 @@ public abstract class BatteryStats implements Parcelable {
int oldPlug = -1;
int oldTemp = -1;
int oldVolt = -1;
while (rec != null) {
while (getNextHistoryLocked(rec)) {
pw.print(" ");
TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
pw.print(" ");
@@ -1803,7 +1819,6 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
}
oldState = rec.states;
rec = rec.next;
}
pw.println("");
}

View File

@@ -51,6 +51,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;
/**
* All information we are collecting about things that can happen that impact
@@ -3834,6 +3835,22 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
private HistoryItem mHistoryIterator;
public boolean startIteratingHistoryLocked() {
return (mHistoryIterator = mHistory) != null;
}
public boolean getNextHistoryLocked(HistoryItem out) {
HistoryItem cur = mHistoryIterator;
if (cur == null) {
return false;
}
out.setTo(cur);
mHistoryIterator = cur.next;
return true;
}
@Override
public HistoryItem getHistory() {
return mHistory;
@@ -3960,7 +3977,7 @@ public final class BatteryStatsImpl extends BatteryStats {
}
if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
if (mFile != null) {
writeLocked();
writeAsyncLocked();
}
}
}
@@ -4356,11 +4373,22 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public void shutdownLocked() {
writeLocked();
writeSyncLocked();
mShuttingDown = true;
}
public void writeLocked() {
Parcel mPendingWrite = null;
final ReentrantLock mWriteLock = new ReentrantLock();
public void writeAsyncLocked() {
writeLocked(false);
}
public void writeSyncLocked() {
writeLocked(true);
}
void writeLocked(boolean sync) {
if (mFile == null) {
Slog.w("BatteryStats", "writeLocked: no file associated with this instance");
return;
@@ -4370,23 +4398,51 @@ public final class BatteryStatsImpl extends BatteryStats {
return;
}
Parcel out = Parcel.obtain();
writeSummaryToParcel(out);
mLastWriteTime = SystemClock.elapsedRealtime();
if (mPendingWrite != null) {
mPendingWrite.recycle();
}
mPendingWrite = out;
if (sync) {
commitPendingDataToDisk();
} else {
Thread thr = new Thread("BatteryStats-Write") {
@Override
public void run() {
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
commitPendingDataToDisk();
}
};
thr.start();
}
}
public void commitPendingDataToDisk() {
Parcel next;
synchronized (this) {
next = mPendingWrite;
mPendingWrite = null;
mWriteLock.lock();
}
try {
FileOutputStream stream = new FileOutputStream(mFile.chooseForWrite());
Parcel out = Parcel.obtain();
writeSummaryToParcel(out);
stream.write(out.marshall());
out.recycle();
stream.write(next.marshall());
stream.flush();
stream.close();
mFile.commit();
mLastWriteTime = SystemClock.elapsedRealtime();
return;
} catch (IOException e) {
Slog.w("BatteryStats", "Error writing battery statistics", e);
mFile.rollback();
} finally {
next.recycle();
mWriteLock.unlock();
}
mFile.rollback();
}
static byte[] readFully(FileInputStream stream) throws java.io.IOException {