Merge "Include saved battery history chunks into BatteryUsageStats parcel" am: 2f7508a404
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1928178 Change-Id: I942d560d7728f03b547e212842c69b7d6d542e0f
This commit is contained in:
@@ -127,6 +127,7 @@ public final class BatteryUsageStats implements Parcelable {
|
|||||||
private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
|
private final AggregateBatteryConsumer[] mAggregateBatteryConsumers;
|
||||||
private final Parcel mHistoryBuffer;
|
private final Parcel mHistoryBuffer;
|
||||||
private final List<BatteryStats.HistoryTag> mHistoryTagPool;
|
private final List<BatteryStats.HistoryTag> mHistoryTagPool;
|
||||||
|
private final BatteryStatsHistory mBatteryStatsHistory;
|
||||||
|
|
||||||
private BatteryUsageStats(@NonNull Builder builder) {
|
private BatteryUsageStats(@NonNull Builder builder) {
|
||||||
mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
|
mStatsStartTimestampMs = builder.mStatsStartTimestampMs;
|
||||||
@@ -138,6 +139,7 @@ public final class BatteryUsageStats implements Parcelable {
|
|||||||
mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
|
mDischargedPowerUpperBound = builder.mDischargedPowerUpperBoundMah;
|
||||||
mHistoryBuffer = builder.mHistoryBuffer;
|
mHistoryBuffer = builder.mHistoryBuffer;
|
||||||
mHistoryTagPool = builder.mHistoryTagPool;
|
mHistoryTagPool = builder.mHistoryTagPool;
|
||||||
|
mBatteryStatsHistory = builder.mBatteryStatsHistory;
|
||||||
mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs;
|
mBatteryTimeRemainingMs = builder.mBatteryTimeRemainingMs;
|
||||||
mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs;
|
mChargeTimeRemainingMs = builder.mChargeTimeRemainingMs;
|
||||||
mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
|
mCustomPowerComponentNames = builder.mCustomPowerComponentNames;
|
||||||
@@ -289,8 +291,8 @@ public final class BatteryUsageStats implements Parcelable {
|
|||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"Battery history was not requested in the BatteryUsageStatsQuery");
|
"Battery history was not requested in the BatteryUsageStatsQuery");
|
||||||
}
|
}
|
||||||
return new BatteryStatsHistoryIterator(new BatteryStatsHistory(mHistoryBuffer),
|
|
||||||
mHistoryTagPool);
|
return new BatteryStatsHistoryIterator(mBatteryStatsHistory, mHistoryTagPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -356,7 +358,10 @@ public final class BatteryUsageStats implements Parcelable {
|
|||||||
tag.poolIdx = source.readInt();
|
tag.poolIdx = source.readInt();
|
||||||
mHistoryTagPool.add(tag);
|
mHistoryTagPool.add(tag);
|
||||||
}
|
}
|
||||||
|
mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
|
||||||
|
mBatteryStatsHistory.readFromBatteryUsageStatsParcel(source);
|
||||||
} else {
|
} else {
|
||||||
|
mBatteryStatsHistory = null;
|
||||||
mHistoryBuffer = null;
|
mHistoryBuffer = null;
|
||||||
mHistoryTagPool = null;
|
mHistoryTagPool = null;
|
||||||
}
|
}
|
||||||
@@ -404,6 +409,7 @@ public final class BatteryUsageStats implements Parcelable {
|
|||||||
dest.writeInt(tag.uid);
|
dest.writeInt(tag.uid);
|
||||||
dest.writeInt(tag.poolIdx);
|
dest.writeInt(tag.poolIdx);
|
||||||
}
|
}
|
||||||
|
mBatteryStatsHistory.writeToBatteryUsageStatsParcel(dest);
|
||||||
} else {
|
} else {
|
||||||
dest.writeBoolean(false);
|
dest.writeBoolean(false);
|
||||||
}
|
}
|
||||||
@@ -757,6 +763,7 @@ public final class BatteryUsageStats implements Parcelable {
|
|||||||
new SparseArray<>();
|
new SparseArray<>();
|
||||||
private Parcel mHistoryBuffer;
|
private Parcel mHistoryBuffer;
|
||||||
private List<BatteryStats.HistoryTag> mHistoryTagPool;
|
private List<BatteryStats.HistoryTag> mHistoryTagPool;
|
||||||
|
private BatteryStatsHistory mBatteryStatsHistory;
|
||||||
|
|
||||||
public Builder(@NonNull String[] customPowerComponentNames) {
|
public Builder(@NonNull String[] customPowerComponentNames) {
|
||||||
this(customPowerComponentNames, false);
|
this(customPowerComponentNames, false);
|
||||||
@@ -865,10 +872,12 @@ public final class BatteryUsageStats implements Parcelable {
|
|||||||
* Sets the parceled recent history.
|
* Sets the parceled recent history.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public Builder setBatteryHistory(Parcel historyBuffer,
|
public Builder setBatteryHistory(@NonNull Parcel historyBuffer,
|
||||||
List<BatteryStats.HistoryTag> historyTagPool) {
|
@NonNull List<BatteryStats.HistoryTag> historyTagPool,
|
||||||
|
@NonNull BatteryStatsHistory batteryStatsHistory) {
|
||||||
mHistoryBuffer = historyBuffer;
|
mHistoryBuffer = historyBuffer;
|
||||||
mHistoryTagPool = historyTagPool;
|
mHistoryTagPool = historyTagPool;
|
||||||
|
mBatteryStatsHistory = batteryStatsHistory;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,6 +160,11 @@ public class BatteryStatsHistory {
|
|||||||
mHistoryDir = null;
|
mHistoryDir = null;
|
||||||
mHistoryBuffer = historyBuffer;
|
mHistoryBuffer = historyBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getHistoryDirectory() {
|
||||||
|
return mHistoryDir;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the active file that mHistoryBuffer is backed up into.
|
* Set the active file that mHistoryBuffer is backed up into.
|
||||||
*
|
*
|
||||||
@@ -375,12 +380,24 @@ public class BatteryStatsHistory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read all history files and serialize into a big Parcel. This is to send history files to
|
* Read all history files and serialize into a big Parcel.
|
||||||
* Settings app since Settings app can not access /data/system directory.
|
* Checkin file calls this method.
|
||||||
* Checkin file also call this method.
|
|
||||||
* @param out the output parcel
|
* @param out the output parcel
|
||||||
*/
|
*/
|
||||||
public void writeToParcel(Parcel out) {
|
public void writeToParcel(Parcel out) {
|
||||||
|
writeToParcel(out, false /* useBlobs */);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read all history files and serialize into a big Parcel. This is to send history files to
|
||||||
|
* Settings app since Settings app can not access /data/system directory.
|
||||||
|
* @param out the output parcel
|
||||||
|
*/
|
||||||
|
public void writeToBatteryUsageStatsParcel(Parcel out) {
|
||||||
|
writeToParcel(out, true /* useBlobs */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeToParcel(Parcel out, boolean useBlobs) {
|
||||||
final long start = SystemClock.uptimeMillis();
|
final long start = SystemClock.uptimeMillis();
|
||||||
out.writeInt(mFileNumbers.size() - 1);
|
out.writeInt(mFileNumbers.size() - 1);
|
||||||
for(int i = 0; i < mFileNumbers.size() - 1; i++) {
|
for(int i = 0; i < mFileNumbers.size() - 1; i++) {
|
||||||
@@ -391,26 +408,42 @@ public class BatteryStatsHistory {
|
|||||||
} catch(Exception e) {
|
} catch(Exception e) {
|
||||||
Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
|
Slog.e(TAG, "Error reading file "+ file.getBaseFile().getPath(), e);
|
||||||
}
|
}
|
||||||
|
if (useBlobs) {
|
||||||
|
out.writeBlob(raw);
|
||||||
|
} else {
|
||||||
|
// Avoiding blobs in the check-in file for compatibility
|
||||||
out.writeByteArray(raw);
|
out.writeByteArray(raw);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (DEBUG) {
|
if (DEBUG) {
|
||||||
Slog.d(TAG, "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start));
|
Slog.d(TAG, "writeToParcel duration ms:" + (SystemClock.uptimeMillis() - start));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is for Settings app, when Settings app receives big history parcel, it call
|
* This is for the check-in file, which has all history files embedded.
|
||||||
* this method to parse it into list of parcels.
|
|
||||||
* Checkin file also call this method.
|
|
||||||
* @param in the input parcel.
|
* @param in the input parcel.
|
||||||
*/
|
*/
|
||||||
public void readFromParcel(Parcel in) {
|
public void readFromParcel(Parcel in) {
|
||||||
|
readFromParcel(in, false /* useBlobs */);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is for Settings app, when Settings app receives big history parcel, it calls
|
||||||
|
* this method to parse it into list of parcels.
|
||||||
|
* @param in the input parcel.
|
||||||
|
*/
|
||||||
|
public void readFromBatteryUsageStatsParcel(Parcel in) {
|
||||||
|
readFromParcel(in, true /* useBlobs */);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readFromParcel(Parcel in, boolean useBlobs) {
|
||||||
final long start = SystemClock.uptimeMillis();
|
final long start = SystemClock.uptimeMillis();
|
||||||
mHistoryParcels = new ArrayList<>();
|
mHistoryParcels = new ArrayList<>();
|
||||||
final int count = in.readInt();
|
final int count = in.readInt();
|
||||||
for(int i = 0; i < count; i++) {
|
for(int i = 0; i < count; i++) {
|
||||||
byte[] temp = in.createByteArray();
|
byte[] temp = useBlobs ? in.readBlob() : in.createByteArray();
|
||||||
if (temp.length == 0) {
|
if (temp == null || temp.length == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Parcel p = Parcel.obtain();
|
Parcel p = Parcel.obtain();
|
||||||
|
|||||||
@@ -1200,12 +1200,21 @@ public class BatteryStatsImpl extends BatteryStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public BatteryStatsImpl(Clocks clocks) {
|
public BatteryStatsImpl(Clocks clocks) {
|
||||||
|
this(clocks, (File) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BatteryStatsImpl(Clocks clocks, File historyDirectory) {
|
||||||
init(clocks);
|
init(clocks);
|
||||||
mStartClockTimeMs = clocks.currentTimeMillis();
|
mStartClockTimeMs = clocks.currentTimeMillis();
|
||||||
mStatsFile = null;
|
|
||||||
mCheckinFile = null;
|
mCheckinFile = null;
|
||||||
mDailyFile = null;
|
mDailyFile = null;
|
||||||
|
if (historyDirectory == null) {
|
||||||
|
mStatsFile = null;
|
||||||
mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
|
mBatteryStatsHistory = new BatteryStatsHistory(mHistoryBuffer);
|
||||||
|
} else {
|
||||||
|
mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
|
||||||
|
mBatteryStatsHistory = new BatteryStatsHistory(this, historyDirectory, mHistoryBuffer);
|
||||||
|
}
|
||||||
mHandler = null;
|
mHandler = null;
|
||||||
mPlatformIdleStateCallback = null;
|
mPlatformIdleStateCallback = null;
|
||||||
mMeasuredEnergyRetriever = null;
|
mMeasuredEnergyRetriever = null;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import android.util.SparseArray;
|
|||||||
|
|
||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -203,7 +204,12 @@ public class BatteryUsageStatsProvider {
|
|||||||
tags.add(tag);
|
tags.add(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
batteryUsageStatsBuilder.setBatteryHistory(historyBuffer, tags);
|
final File systemDir =
|
||||||
|
batteryStatsImpl.mBatteryStatsHistory.getHistoryDirectory().getParentFile();
|
||||||
|
final BatteryStatsHistory batteryStatsHistory =
|
||||||
|
new BatteryStatsHistory(batteryStatsImpl, systemDir, historyBuffer);
|
||||||
|
|
||||||
|
batteryUsageStatsBuilder.setBatteryHistory(historyBuffer, tags, batteryStatsHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
return batteryUsageStatsBuilder.build();
|
return batteryUsageStatsBuilder.build();
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ import androidx.test.InstrumentationRegistry;
|
|||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import libcore.testing.io.TestIoUtils;
|
||||||
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -52,8 +54,11 @@ public class BatteryUsageStatsProviderTest {
|
|||||||
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
|
private static final int APP_UID = Process.FIRST_APPLICATION_UID + 42;
|
||||||
private static final long MINUTE_IN_MS = 60 * 1000;
|
private static final long MINUTE_IN_MS = 60 * 1000;
|
||||||
|
|
||||||
|
private final File mHistoryDir =
|
||||||
|
TestIoUtils.createTemporaryDirectory(getClass().getSimpleName());
|
||||||
|
|
||||||
@Rule
|
@Rule
|
||||||
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345)
|
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule(12345, mHistoryDir)
|
||||||
.setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0);
|
.setAveragePower(PowerProfile.POWER_FLASHLIGHT, 360.0);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import org.junit.runner.Description;
|
|||||||
import org.junit.runners.model.Statement;
|
import org.junit.runners.model.Statement;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class BatteryUsageStatsRule implements TestRule {
|
public class BatteryUsageStatsRule implements TestRule {
|
||||||
@@ -57,14 +58,18 @@ public class BatteryUsageStatsRule implements TestRule {
|
|||||||
private boolean mScreenOn;
|
private boolean mScreenOn;
|
||||||
|
|
||||||
public BatteryUsageStatsRule() {
|
public BatteryUsageStatsRule() {
|
||||||
this(0);
|
this(0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BatteryUsageStatsRule(long currentTime) {
|
public BatteryUsageStatsRule(long currentTime) {
|
||||||
|
this(currentTime, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BatteryUsageStatsRule(long currentTime, File historyDir) {
|
||||||
Context context = InstrumentationRegistry.getContext();
|
Context context = InstrumentationRegistry.getContext();
|
||||||
mPowerProfile = spy(new PowerProfile(context, true /* forTest */));
|
mPowerProfile = spy(new PowerProfile(context, true /* forTest */));
|
||||||
mMockClocks.currentTime = currentTime;
|
mMockClocks.currentTime = currentTime;
|
||||||
mBatteryStats = new MockBatteryStatsImpl(mMockClocks);
|
mBatteryStats = new MockBatteryStatsImpl(mMockClocks, historyDir);
|
||||||
mBatteryStats.setPowerProfile(mPowerProfile);
|
mBatteryStats.setPowerProfile(mPowerProfile);
|
||||||
mBatteryStats.onSystemReady();
|
mBatteryStats.onSystemReady();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader
|
|||||||
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
|
import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidUserSysTimeReader;
|
||||||
import com.android.internal.power.MeasuredEnergyStats;
|
import com.android.internal.power.MeasuredEnergyStats;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
@@ -44,7 +45,12 @@ public class MockBatteryStatsImpl extends BatteryStatsImpl {
|
|||||||
private NetworkStats mNetworkStats;
|
private NetworkStats mNetworkStats;
|
||||||
|
|
||||||
MockBatteryStatsImpl(Clocks clocks) {
|
MockBatteryStatsImpl(Clocks clocks) {
|
||||||
super(clocks);
|
this(clocks, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
MockBatteryStatsImpl(Clocks clocks, File historyDirectory) {
|
||||||
|
super(clocks, historyDirectory);
|
||||||
|
|
||||||
this.clocks = mClocks;
|
this.clocks = mClocks;
|
||||||
initTimersAndCounters();
|
initTimersAndCounters();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user