summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/system-current.txt1
-rw-r--r--api/system-removed.txt4
-rw-r--r--cmds/bootanimation/Android.mk7
-rw-r--r--cmds/bootanimation/iot/iotbootanimation_main.cpp13
-rw-r--r--cmds/incidentd/src/PrivacyBuffer.cpp9
-rw-r--r--core/java/android/os/BatteryStats.java512
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java40
-rw-r--r--core/jni/eventlog_helper.h103
-rw-r--r--core/proto/android/os/batterystats.proto379
-rw-r--r--core/proto/android/telephony/signalstrength.proto35
-rw-r--r--core/res/res/values-mcc001-mnc01/strings.xml22
-rw-r--r--core/res/res/values-mcc310-mnc030/strings.xml1
-rw-r--r--core/res/res/values-mcc310-mnc150/strings.xml22
-rw-r--r--core/res/res/values-mcc310-mnc170/strings.xml1
-rw-r--r--core/res/res/values-mcc310-mnc280/strings.xml1
-rw-r--r--core/res/res/values-mcc310-mnc410/strings.xml1
-rw-r--r--core/res/res/values-mcc310-mnc560/strings.xml1
-rw-r--r--core/res/res/values-mcc310-mnc950/strings.xml1
-rw-r--r--core/res/res/values-mcc311-mnc180/strings.xml1
-rw-r--r--core/res/res/values-mcc312-mnc670/strings.xml22
-rw-r--r--core/res/res/values-mcc313-mnc100/strings.xml22
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java50
-rw-r--r--libs/protoutil/Android.mk4
-rw-r--r--libs/protoutil/include/android/util/EncodedBuffer.h73
-rw-r--r--libs/protoutil/include/android/util/ProtoOutputStream.h100
-rw-r--r--libs/protoutil/include/android/util/protobuf.h15
-rw-r--r--libs/protoutil/src/EncodedBuffer.cpp132
-rw-r--r--libs/protoutil/src/ProtoOutputStream.cpp652
-rw-r--r--libs/protoutil/src/protobuf.cpp19
-rw-r--r--media/java/android/media/tv/ITvInputHardware.aidl6
-rw-r--r--media/java/android/media/tv/TvInputManager.java7
-rw-r--r--media/jni/android_media_MediaPlayer.cpp2
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java6
-rw-r--r--services/core/java/com/android/server/tv/TvInputHardwareManager.java14
34 files changed, 2120 insertions, 158 deletions
diff --git a/api/system-current.txt b/api/system-current.txt
index ea077fe62aee..9e02b03c0add 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -27217,7 +27217,6 @@ package android.media.tv {
}
public static final class TvInputManager.Hardware {
- method public boolean dispatchKeyEventToHdmi(android.view.KeyEvent);
method public void overrideAudioSink(int, java.lang.String, int, int, int);
method public void setStreamVolume(float);
method public boolean setSurface(android.view.Surface, android.media.tv.TvStreamConfig);
diff --git a/api/system-removed.txt b/api/system-removed.txt
index 7ee261e88fc7..639877fae6e2 100644
--- a/api/system-removed.txt
+++ b/api/system-removed.txt
@@ -275,6 +275,10 @@ package android.media.tv {
method public android.media.tv.TvInputManager.Hardware acquireTvInputHardware(int, android.media.tv.TvInputManager.HardwareCallback, android.media.tv.TvInputInfo);
}
+ public static final class TvInputManager.Hardware {
+ method public boolean dispatchKeyEventToHdmi(android.view.KeyEvent);
+ }
+
public class TvView extends android.view.ViewGroup {
method public void requestUnblockContent(android.media.tv.TvContentRating);
}
diff --git a/cmds/bootanimation/Android.mk b/cmds/bootanimation/Android.mk
index b16188e9d82e..e5d35b3b8a0e 100644
--- a/cmds/bootanimation/Android.mk
+++ b/cmds/bootanimation/Android.mk
@@ -34,13 +34,6 @@ LOCAL_SRC_FILES += \
iot/BootAction.cpp \
iot/BootParameters.cpp \
-LOCAL_SHARED_LIBRARIES += \
- libandroidthings \
- libbase \
- libbinder \
-
-LOCAL_STATIC_LIBRARIES += cpufeatures
-
else
LOCAL_SRC_FILES += \
diff --git a/cmds/bootanimation/iot/iotbootanimation_main.cpp b/cmds/bootanimation/iot/iotbootanimation_main.cpp
index 742f9c24f3a0..00cef430135e 100644
--- a/cmds/bootanimation/iot/iotbootanimation_main.cpp
+++ b/cmds/bootanimation/iot/iotbootanimation_main.cpp
@@ -16,7 +16,7 @@
#define LOG_TAG "IotBootAnimation"
-#include <android-base/file.h>
+#include <base/files/file_util.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
@@ -31,13 +31,14 @@
#include "BootParameters.h"
using namespace android;
-using android::base::ReadFileToString;
// Create a typedef for readability.
typedef android::BootAnimation::Animation Animation;
namespace {
+constexpr const char* kDefaultLibName = "libbootaction.so";
+
class BootActionAnimationCallbacks : public android::BootAnimation::Callbacks {
public:
BootActionAnimationCallbacks(std::unique_ptr<BootParameters> bootParameters)
@@ -49,11 +50,13 @@ public:
// This value is optionally provided by the user and will be written to
// /oem/oem.prop.
char property[PROP_VALUE_MAX] = {0};
- if (property_get("ro.oem.bootactions.lib", property, "") < 1) {
- ALOGI("No bootaction specified");
+ property_get("ro.oem.bootactions.lib", property, kDefaultLibName);
+ library_path += property;
+
+ if (!::base::PathExists(::base::FilePath(library_path))) {
+ ALOGI("Skipping boot actions: %s does not exist", library_path.c_str());
return;
}
- library_path += property;
mBootAction = new BootAction();
if (!mBootAction->init(library_path, mBootParameters->getParameters())) {
diff --git a/cmds/incidentd/src/PrivacyBuffer.cpp b/cmds/incidentd/src/PrivacyBuffer.cpp
index 07a064cf044b..37f6ed710cce 100644
--- a/cmds/incidentd/src/PrivacyBuffer.cpp
+++ b/cmds/incidentd/src/PrivacyBuffer.cpp
@@ -33,18 +33,18 @@ write_field_or_skip(EncodedBuffer::iterator* iter, EncodedBuffer* buf, uint8_t w
{
EncodedBuffer::Pointer snapshot = iter->rp()->copy();
size_t bytesToWrite = 0;
- uint32_t varint = 0;
+ uint64_t varint = 0;
switch (wireType) {
case WIRE_TYPE_VARINT:
varint = iter->readRawVarint();
- if(!skip) return buf->writeRawVarint(varint);
+ if(!skip) return buf->writeRawVarint64(varint);
break;
case WIRE_TYPE_FIXED64:
bytesToWrite = 8;
break;
case WIRE_TYPE_LENGTH_DELIMITED:
bytesToWrite = iter->readRawVarint();
- if(!skip) buf->writeRawVarint(bytesToWrite);
+ if(!skip) buf->writeRawVarint32(bytesToWrite);
break;
case WIRE_TYPE_FIXED32:
bytesToWrite = 4;
@@ -76,7 +76,6 @@ stripField(EncodedBuffer::iterator* iter, EncodedBuffer* buf, const Privacy* par
uint8_t wireType = read_wire_type(varint);
uint32_t fieldId = read_field_id(varint);
const Privacy* policy = parentPolicy->lookup(fieldId);
-
if (policy == NULL || !policy->IsMessageType() || !policy->HasChildren()) {
bool skip = !spec.CheckPremission(policy);
size_t amt = buf->size();
@@ -99,7 +98,7 @@ stripField(EncodedBuffer::iterator* iter, EncodedBuffer* buf, const Privacy* par
}
buf->writeHeader(fieldId, wireType);
- buf->writeRawVarint(finalSize);
+ buf->writeRawVarint32(finalSize);
while (!q.empty()) {
EncodedBuffer* subField = q.front();
EncodedBuffer::iterator it = subField->begin();
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 988192797f59..450ced4b9897 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1911,6 +1911,13 @@ public abstract class BatteryStats implements Parcelable {
long elapsedRealtimeUs, int which);
/**
+ * Returns the {@link Timer} object that tracks the given screen brightness.
+ *
+ * {@hide}
+ */
+ public abstract Timer getScreenBrightnessTimer(int brightnessBin);
+
+ /**
* Returns the time in microseconds that power save mode has been enabled while the device was
* running on battery.
*
@@ -2019,6 +2026,14 @@ public abstract class BatteryStats implements Parcelable {
long elapsedRealtimeUs, int which);
/**
+ * Returns the {@link Timer} object that tracks how much the phone has been trying to
+ * acquire a signal.
+ *
+ * {@hide}
+ */
+ public abstract Timer getPhoneSignalScanningTimer();
+
+ /**
* Returns the number of times the phone has entered the given signal strength.
*
* {@hide}
@@ -2026,6 +2041,12 @@ public abstract class BatteryStats implements Parcelable {
public abstract int getPhoneSignalStrengthCount(int strengthBin, int which);
/**
+ * Return the {@link Timer} object used to track the given signal strength's duration and
+ * counts.
+ */
+ protected abstract Timer getPhoneSignalStrengthTimer(int strengthBin);
+
+ /**
* Returns the time in microseconds that the mobile network has been active
* (in a high power state).
*
@@ -2108,6 +2129,11 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract int getPhoneDataConnectionCount(int dataType, int which);
+ /**
+ * Returns the {@link Timer} object that tracks the phone's data connection type stats.
+ */
+ public abstract Timer getPhoneDataConnectionTimer(int dataType);
+
public static final int WIFI_SUPPL_STATE_INVALID = 0;
public static final int WIFI_SUPPL_STATE_DISCONNECTED = 1;
public static final int WIFI_SUPPL_STATE_INTERFACE_DISABLED = 2;
@@ -2267,6 +2293,13 @@ public abstract class BatteryStats implements Parcelable {
public abstract int getWifiStateCount(int wifiState, int which);
/**
+ * Returns the {@link Timer} object that tracks the given WiFi state.
+ *
+ * {@hide}
+ */
+ public abstract Timer getWifiStateTimer(int wifiState);
+
+ /**
* Returns the time in microseconds that the wifi supplicant has been
* in a given state.
*
@@ -2282,6 +2315,13 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract int getWifiSupplStateCount(int state, int which);
+ /**
+ * Returns the {@link Timer} object that tracks the given wifi supplicant state.
+ *
+ * {@hide}
+ */
+ public abstract Timer getWifiSupplStateTimer(int state);
+
public static final int NUM_WIFI_SIGNAL_STRENGTH_BINS = 5;
/**
@@ -2301,6 +2341,13 @@ public abstract class BatteryStats implements Parcelable {
public abstract int getWifiSignalStrengthCount(int strengthBin, int which);
/**
+ * Returns the {@link Timer} object that tracks the given WIFI signal strength.
+ *
+ * {@hide}
+ */
+ public abstract Timer getWifiSignalStrengthTimer(int strengthBin);
+
+ /**
* Returns the time in microseconds that the flashlight has been on while the device was
* running on battery.
*
@@ -2487,13 +2534,13 @@ public abstract class BatteryStats implements Parcelable {
public abstract int getDischargeAmountScreenOffSinceCharge();
/**
- * Get the amount the battery has discharged while the screen was doze,
+ * Get the amount the battery has discharged while the screen was dozing,
* since the last time power was unplugged.
*/
public abstract int getDischargeAmountScreenDoze();
/**
- * Get the amount the battery has discharged while the screen was doze,
+ * Get the amount the battery has discharged while the screen was dozing,
* since the last time the device was charged.
*/
public abstract int getDischargeAmountScreenDozeSinceCharge();
@@ -2626,20 +2673,20 @@ public abstract class BatteryStats implements Parcelable {
* micro-Ampere-hours. This will be non-zero only if the device's battery has
* a coulomb counter.
*/
- public abstract long getMahDischargeScreenOff(int which);
+ public abstract long getUahDischargeScreenOff(int which);
/**
* Return the amount of battery discharge while the screen was in doze mode, measured in
* micro-Ampere-hours. This will be non-zero only if the device's battery has
* a coulomb counter.
*/
- public abstract long getMahDischargeScreenDoze(int which);
+ public abstract long getUahDischargeScreenDoze(int which);
/**
* Return the amount of battery discharge measured in micro-Ampere-hours. This will be
* non-zero only if the device's battery has a coulomb counter.
*/
- public abstract long getMahDischarge(int which);
+ public abstract long getUahDischarge(int which);
/**
* Returns the estimated real battery capacity, which may be less than the capacity
@@ -2984,7 +3031,7 @@ public abstract class BatteryStats implements Parcelable {
final long totalTime = (timer.getTotalTimeLocked(rawRealtime, which) + 500)
/ 1000;
final int count = timer.getCountLocked(which);
- if (totalTime != 0) {
+ if (totalTime != 0 || count != 0) {
dumpLine(pw, uid, category, type, totalTime, count);
}
}
@@ -3000,12 +3047,12 @@ public abstract class BatteryStats implements Parcelable {
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
*/
private static void dumpTimer(ProtoOutputStream proto, long fieldId,
- Timer timer, long rawRealtime, int which) {
+ Timer timer, long rawRealtimeUs, int which) {
if (timer == null) {
return;
}
// Convert from microseconds to milliseconds with rounding
- final long totalTimeMs = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+ final long totalTimeMs = (timer.getTotalTimeLocked(rawRealtimeUs, which) + 500) / 1000;
final int count = timer.getCountLocked(which);
if (totalTimeMs != 0 || count != 0) {
final long token = proto.start(fieldId);
@@ -3191,13 +3238,13 @@ public abstract class BatteryStats implements Parcelable {
/**
* Checkin server version of dump to produce more compact, computer-readable log.
*
- * NOTE: all times are expressed in 'ms'.
+ * NOTE: all times are expressed in microseconds, unless specified otherwise.
*/
public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid,
boolean wifiOnly) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
- final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
- final long rawRealtimeMs = (rawRealtime + 500) / 1000;
+ final long rawRealtimeMs = SystemClock.elapsedRealtime();
+ final long rawRealtime = rawRealtimeMs * 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
@@ -3220,9 +3267,9 @@ public abstract class BatteryStats implements Parcelable {
rawRealtime, which);
final int connChanges = getNumConnectivityChange(which);
final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
- final long dischargeCount = getMahDischarge(which);
- final long dischargeScreenOffCount = getMahDischargeScreenOff(which);
- final long dischargeScreenDozeCount = getMahDischargeScreenDoze(which);
+ final long dischargeCount = getUahDischarge(which);
+ final long dischargeScreenOffCount = getUahDischargeScreenOff(which);
+ final long dischargeScreenDozeCount = getUahDischargeScreenDoze(which);
final StringBuilder sb = new StringBuilder(128);
@@ -3460,9 +3507,9 @@ public abstract class BatteryStats implements Parcelable {
BatteryStatsHelper.makemAh(helper.getComputedPower()),
BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
+ int uid = 0;
for (int i=0; i<sippers.size(); i++) {
final BatterySipper bs = sippers.get(i);
- int uid = 0;
String label;
switch (bs.drainType) {
case IDLE:
@@ -3503,6 +3550,9 @@ public abstract class BatteryStats implements Parcelable {
case CAMERA:
label = "camera";
break;
+ case MEMORY:
+ label = "memory";
+ break;
default:
label = "???";
}
@@ -3523,6 +3573,7 @@ public abstract class BatteryStats implements Parcelable {
dumpLine(pw, 0 /* uid */, category, GLOBAL_CPU_FREQ_DATA, sb.toString());
}
+ // Dump stats per UID.
for (int iu = 0; iu < NU; iu++) {
final int uid = uidStats.keyAt(iu);
if (reqUid >= 0 && uid != reqUid) {
@@ -4020,7 +4071,7 @@ public abstract class BatteryStats implements Parcelable {
pw.println(sb.toString());
}
- final long dischargeCount = getMahDischarge(which);
+ final long dischargeCount = getUahDischarge(which);
if (dischargeCount >= 0) {
sb.setLength(0);
sb.append(prefix);
@@ -4030,7 +4081,7 @@ public abstract class BatteryStats implements Parcelable {
pw.println(sb.toString());
}
- final long dischargeScreenOffCount = getMahDischargeScreenOff(which);
+ final long dischargeScreenOffCount = getUahDischargeScreenOff(which);
if (dischargeScreenOffCount >= 0) {
sb.setLength(0);
sb.append(prefix);
@@ -4040,7 +4091,7 @@ public abstract class BatteryStats implements Parcelable {
pw.println(sb.toString());
}
- final long dischargeScreenDozeCount = getMahDischargeScreenDoze(which);
+ final long dischargeScreenDozeCount = getUahDischargeScreenDoze(which);
if (dischargeScreenDozeCount >= 0) {
sb.setLength(0);
sb.append(prefix);
@@ -6038,6 +6089,61 @@ public abstract class BatteryStats implements Parcelable {
return true;
}
+ private static void dumpDurationSteps(ProtoOutputStream proto, long fieldId,
+ LevelStepTracker steps) {
+ if (steps == null) {
+ return;
+ }
+ int count = steps.mNumStepDurations;
+ long token;
+ for (int i = 0; i < count; ++i) {
+ token = proto.start(fieldId);
+ proto.write(SystemProto.BatteryLevelStep.DURATION_MS, steps.getDurationAt(i));
+ proto.write(SystemProto.BatteryLevelStep.LEVEL, steps.getLevelAt(i));
+
+ final long initMode = steps.getInitModeAt(i);
+ final long modMode = steps.getModModeAt(i);
+
+ int ds = SystemProto.BatteryLevelStep.DS_MIXED;
+ if ((modMode & STEP_LEVEL_MODE_SCREEN_STATE) == 0) {
+ switch ((int) (initMode & STEP_LEVEL_MODE_SCREEN_STATE) + 1) {
+ case Display.STATE_OFF:
+ ds = SystemProto.BatteryLevelStep.DS_OFF;
+ break;
+ case Display.STATE_ON:
+ ds = SystemProto.BatteryLevelStep.DS_ON;
+ break;
+ case Display.STATE_DOZE:
+ ds = SystemProto.BatteryLevelStep.DS_DOZE;
+ break;
+ case Display.STATE_DOZE_SUSPEND:
+ ds = SystemProto.BatteryLevelStep.DS_DOZE_SUSPEND;
+ break;
+ default:
+ ds = SystemProto.BatteryLevelStep.DS_ERROR;
+ break;
+ }
+ }
+ proto.write(SystemProto.BatteryLevelStep.DISPLAY_STATE, ds);
+
+ int psm = SystemProto.BatteryLevelStep.PSM_MIXED;
+ if ((modMode & STEP_LEVEL_MODE_POWER_SAVE) == 0) {
+ psm = (initMode & STEP_LEVEL_MODE_POWER_SAVE) != 0
+ ? SystemProto.BatteryLevelStep.PSM_ON : SystemProto.BatteryLevelStep.PSM_OFF;
+ }
+ proto.write(SystemProto.BatteryLevelStep.POWER_SAVE_MODE, psm);
+
+ int im = SystemProto.BatteryLevelStep.IM_MIXED;
+ if ((modMode & STEP_LEVEL_MODE_DEVICE_IDLE) == 0) {
+ im = (initMode & STEP_LEVEL_MODE_DEVICE_IDLE) != 0
+ ? SystemProto.BatteryLevelStep.IM_ON : SystemProto.BatteryLevelStep.IM_OFF;
+ }
+ proto.write(SystemProto.BatteryLevelStep.IDLE_MODE, im);
+
+ proto.end(token);
+ }
+ }
+
public static final int DUMP_CHARGED_ONLY = 1<<1;
public static final int DUMP_DAILY_ONLY = 1<<2;
public static final int DUMP_HISTORY_ONLY = 1<<3;
@@ -6463,7 +6569,7 @@ public abstract class BatteryStats implements Parcelable {
}
}
- /** Dump batterystats data to a proto. @hide */
+ /** Dump #STATS_SINCE_CHARGED batterystats data to a proto. @hide */
public void dumpProtoLocked(Context context, FileDescriptor fd, List<ApplicationInfo> apps,
int flags, long historyStart) {
final ProtoOutputStream proto = new ProtoOutputStream(fd);
@@ -6485,10 +6591,376 @@ public abstract class BatteryStats implements Parcelable {
if ((flags & (DUMP_HISTORY_ONLY | DUMP_DAILY_ONLY)) == 0) {
// TODO: implement dumpProtoAppsLocked(proto, apps);
- // TODO: implement dumpProtoSystemLocked(proto);
+ dumpProtoSystemLocked(context, proto, (flags & DUMP_DEVICE_WIFI_ONLY) != 0);
}
proto.end(bToken);
proto.flush();
}
+
+ private void dumpProtoSystemLocked(Context context, ProtoOutputStream proto, boolean wifiOnly) {
+ final long sToken = proto.start(BatteryStatsProto.SYSTEM);
+ final long rawUptimeUs = SystemClock.uptimeMillis() * 1000;
+ final long rawRealtimeMs = SystemClock.elapsedRealtime();
+ final long rawRealtimeUs = rawRealtimeMs * 1000;
+ final int which = STATS_SINCE_CHARGED;
+
+ // Battery data (BATTERY_DATA)
+ long token = proto.start(SystemProto.BATTERY);
+ proto.write(SystemProto.Battery.START_CLOCK_TIME_MS, getStartClockTime());
+ proto.write(SystemProto.Battery.START_COUNT, getStartCount());
+ proto.write(SystemProto.Battery.TOTAL_REALTIME_MS,
+ computeRealtime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.TOTAL_UPTIME_MS,
+ computeUptime(rawUptimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.BATTERY_REALTIME_MS,
+ computeBatteryRealtime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.BATTERY_UPTIME_MS,
+ computeBatteryUptime(rawUptimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.SCREEN_OFF_REALTIME_MS,
+ computeBatteryScreenOffRealtime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.SCREEN_OFF_UPTIME_MS,
+ computeBatteryScreenOffUptime(rawUptimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.SCREEN_DOZE_DURATION_MS,
+ getScreenDozeTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Battery.ESTIMATED_BATTERY_CAPACITY_MAH,
+ getEstimatedBatteryCapacity());
+ proto.write(SystemProto.Battery.MIN_LEARNED_BATTERY_CAPACITY_UAH,
+ getMinLearnedBatteryCapacity());
+ proto.write(SystemProto.Battery.MAX_LEARNED_BATTERY_CAPACITY_UAH,
+ getMaxLearnedBatteryCapacity());
+ proto.end(token);
+
+ // Battery discharge (BATTERY_DISCHARGE_DATA)
+ token = proto.start(SystemProto.BATTERY_DISCHARGE);
+ proto.write(SystemProto.BatteryDischarge.LOWER_BOUND_SINCE_CHARGE,
+ getLowDischargeAmountSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.UPPER_BOUND_SINCE_CHARGE,
+ getHighDischargeAmountSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.SCREEN_ON_SINCE_CHARGE,
+ getDischargeAmountScreenOnSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.SCREEN_OFF_SINCE_CHARGE,
+ getDischargeAmountScreenOffSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.SCREEN_DOZE_SINCE_CHARGE,
+ getDischargeAmountScreenDozeSinceCharge());
+ proto.write(SystemProto.BatteryDischarge.TOTAL_MAH,
+ getUahDischarge(which) / 1000);
+ proto.write(SystemProto.BatteryDischarge.TOTAL_MAH_SCREEN_OFF,
+ getUahDischargeScreenOff(which) / 1000);
+ proto.write(SystemProto.BatteryDischarge.TOTAL_MAH_SCREEN_DOZE,
+ getUahDischargeScreenDoze(which) / 1000);
+ proto.end(token);
+
+ // Time remaining
+ long timeRemainingUs = computeChargeTimeRemaining(rawRealtimeUs);
+ if (timeRemainingUs >= 0) {
+ // Charge time remaining (CHARGE_TIME_REMAIN_DATA)
+ proto.write(SystemProto.CHARGE_TIME_REMAINING_MS, timeRemainingUs / 1000);
+ } else {
+ timeRemainingUs = computeBatteryTimeRemaining(rawRealtimeUs);
+ // Discharge time remaining (DISCHARGE_TIME_REMAIN_DATA)
+ if (timeRemainingUs >= 0) {
+ proto.write(SystemProto.DISCHARGE_TIME_REMAINING_MS, timeRemainingUs / 1000);
+ } else {
+ proto.write(SystemProto.DISCHARGE_TIME_REMAINING_MS, -1);
+ }
+ }
+
+ // Charge step (CHARGE_STEP_DATA)
+ dumpDurationSteps(proto, SystemProto.CHARGE_STEP, getChargeLevelStepTracker());
+
+ // Phone data connection (DATA_CONNECTION_TIME_DATA and DATA_CONNECTION_COUNT_DATA)
+ for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; ++i) {
+ token = proto.start(SystemProto.DATA_CONNECTION);
+ proto.write(SystemProto.DataConnection.NAME, i);
+ dumpTimer(proto, SystemProto.DataConnection.TOTAL, getPhoneDataConnectionTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Discharge step (DISCHARGE_STEP_DATA)
+ dumpDurationSteps(proto, SystemProto.DISCHARGE_STEP, getDischargeLevelStepTracker());
+
+ // CPU frequencies (GLOBAL_CPU_FREQ_DATA)
+ final long[] cpuFreqs = getCpuFreqs();
+ if (cpuFreqs != null) {
+ for (long i : cpuFreqs) {
+ proto.write(SystemProto.CPU_FREQUENCY, i);
+ }
+ }
+
+ // Bluetooth controller (GLOBAL_BLUETOOTH_CONTROLLER_DATA)
+ dumpControllerActivityProto(proto, SystemProto.GLOBAL_BLUETOOTH_CONTROLLER,
+ getBluetoothControllerActivity(), which);
+
+ // Modem controller (GLOBAL_MODEM_CONTROLLER_DATA)
+ dumpControllerActivityProto(proto, SystemProto.GLOBAL_MODEM_CONTROLLER,
+ getModemControllerActivity(), which);
+
+ // Global network data (GLOBAL_NETWORK_DATA)
+ token = proto.start(SystemProto.GLOBAL_NETWORK);
+ proto.write(SystemProto.GlobalNetwork.MOBILE_BYTES_RX,
+ getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.MOBILE_BYTES_TX,
+ getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.MOBILE_PACKETS_RX,
+ getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.MOBILE_PACKETS_TX,
+ getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.WIFI_BYTES_RX,
+ getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.WIFI_BYTES_TX,
+ getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.WIFI_PACKETS_RX,
+ getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.WIFI_PACKETS_TX,
+ getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.BT_BYTES_RX,
+ getNetworkActivityBytes(NETWORK_BT_RX_DATA, which));
+ proto.write(SystemProto.GlobalNetwork.BT_BYTES_TX,
+ getNetworkActivityBytes(NETWORK_BT_TX_DATA, which));
+ proto.end(token);
+
+ // Wifi controller (GLOBAL_WIFI_CONTROLLER_DATA)
+ dumpControllerActivityProto(proto, SystemProto.GLOBAL_WIFI_CONTROLLER,
+ getWifiControllerActivity(), which);
+
+
+ // Global wifi (GLOBAL_WIFI_DATA)
+ token = proto.start(SystemProto.GLOBAL_WIFI);
+ proto.write(SystemProto.GlobalWifi.ON_DURATION_MS,
+ getWifiOnTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.GlobalWifi.RUNNING_DURATION_MS,
+ getGlobalWifiRunningTime(rawRealtimeUs, which) / 1000);
+ proto.end(token);
+
+ // Kernel wakelock (KERNEL_WAKELOCK_DATA)
+ final Map<String, ? extends Timer> kernelWakelocks = getKernelWakelockStats();
+ for (Map.Entry<String, ? extends Timer> ent : kernelWakelocks.entrySet()) {
+ token = proto.start(SystemProto.KERNEL_WAKELOCK);
+ proto.write(SystemProto.KernelWakelock.NAME, ent.getKey());
+ dumpTimer(proto, SystemProto.KernelWakelock.TOTAL, ent.getValue(),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Misc (MISC_DATA)
+ // Calculate wakelock times across all uids.
+ long fullWakeLockTimeTotalUs = 0;
+ long partialWakeLockTimeTotalUs = 0;
+
+ final SparseArray<? extends Uid> uidStats = getUidStats();
+ for (int iu = 0; iu < uidStats.size(); iu++) {
+ final Uid u = uidStats.valueAt(iu);
+
+ final ArrayMap<String, ? extends BatteryStats.Uid.Wakelock> wakelocks =
+ u.getWakelockStats();
+ for (int iw = wakelocks.size() - 1; iw >= 0; --iw) {
+ final Uid.Wakelock wl = wakelocks.valueAt(iw);
+
+ final Timer fullWakeTimer = wl.getWakeTime(WAKE_TYPE_FULL);
+ if (fullWakeTimer != null) {
+ fullWakeLockTimeTotalUs += fullWakeTimer.getTotalTimeLocked(rawRealtimeUs,
+ which);
+ }
+
+ final Timer partialWakeTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+ if (partialWakeTimer != null) {
+ partialWakeLockTimeTotalUs += partialWakeTimer.getTotalTimeLocked(
+ rawRealtimeUs, which);
+ }
+ }
+ }
+ token = proto.start(SystemProto.MISC);
+ proto.write(SystemProto.Misc.SCREEN_ON_DURATION_MS,
+ getScreenOnTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.PHONE_ON_DURATION_MS,
+ getPhoneOnTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.FULL_WAKELOCK_TOTAL_DURATION_MS,
+ fullWakeLockTimeTotalUs / 1000);
+ proto.write(SystemProto.Misc.PARTIAL_WAKELOCK_TOTAL_DURATION_MS,
+ partialWakeLockTimeTotalUs / 1000);
+ proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_DURATION_MS,
+ getMobileRadioActiveTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_ADJUSTED_TIME_MS,
+ getMobileRadioActiveAdjustedTime(which) / 1000);
+ proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_COUNT,
+ getMobileRadioActiveCount(which));
+ proto.write(SystemProto.Misc.MOBILE_RADIO_ACTIVE_UNKNOWN_DURATION_MS,
+ getMobileRadioActiveUnknownTime(which) / 1000);
+ proto.write(SystemProto.Misc.INTERACTIVE_DURATION_MS,
+ getInteractiveTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.BATTERY_SAVER_MODE_ENABLED_DURATION_MS,
+ getPowerSaveModeEnabledTime(rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.NUM_CONNECTIVITY_CHANGES,
+ getNumConnectivityChange(which));
+ proto.write(SystemProto.Misc.DEEP_DOZE_ENABLED_DURATION_MS,
+ getDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP, rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.DEEP_DOZE_COUNT,
+ getDeviceIdleModeCount(DEVICE_IDLE_MODE_DEEP, which));
+ proto.write(SystemProto.Misc.DEEP_DOZE_IDLING_DURATION_MS,
+ getDeviceIdlingTime(DEVICE_IDLE_MODE_DEEP, rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.DEEP_DOZE_IDLING_COUNT,
+ getDeviceIdlingCount(DEVICE_IDLE_MODE_DEEP, which));
+ proto.write(SystemProto.Misc.LONGEST_DEEP_DOZE_DURATION_MS,
+ getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_DEEP));
+ proto.write(SystemProto.Misc.LIGHT_DOZE_ENABLED_DURATION_MS,
+ getDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT, rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.LIGHT_DOZE_COUNT,
+ getDeviceIdleModeCount(DEVICE_IDLE_MODE_LIGHT, which));
+ proto.write(SystemProto.Misc.LIGHT_DOZE_IDLING_DURATION_MS,
+ getDeviceIdlingTime(DEVICE_IDLE_MODE_LIGHT, rawRealtimeUs, which) / 1000);
+ proto.write(SystemProto.Misc.LIGHT_DOZE_IDLING_COUNT,
+ getDeviceIdlingCount(DEVICE_IDLE_MODE_LIGHT, which));
+ proto.write(SystemProto.Misc.LONGEST_LIGHT_DOZE_DURATION_MS,
+ getLongestDeviceIdleModeTime(DEVICE_IDLE_MODE_LIGHT));
+ proto.end(token);
+
+ final BatteryStatsHelper helper = new BatteryStatsHelper(context, false, wifiOnly);
+ helper.create(this);
+ helper.refreshStats(which, UserHandle.USER_ALL);
+
+ // Power use item (POWER_USE_ITEM_DATA)
+ final List<BatterySipper> sippers = helper.getUsageList();
+ if (sippers != null) {
+ for (int i = 0; i < sippers.size(); ++i) {
+ final BatterySipper bs = sippers.get(i);
+ int n = SystemProto.PowerUseItem.UNKNOWN_SIPPER;
+ int uid = 0;
+ switch (bs.drainType) {
+ case IDLE:
+ n = SystemProto.PowerUseItem.IDLE;
+ break;
+ case CELL:
+ n = SystemProto.PowerUseItem.CELL;
+ break;
+ case PHONE:
+ n = SystemProto.PowerUseItem.PHONE;
+ break;
+ case WIFI:
+ n = SystemProto.PowerUseItem.WIFI;
+ break;
+ case BLUETOOTH:
+ n = SystemProto.PowerUseItem.BLUETOOTH;
+ break;
+ case SCREEN:
+ n = SystemProto.PowerUseItem.SCREEN;
+ break;
+ case FLASHLIGHT:
+ n = SystemProto.PowerUseItem.FLASHLIGHT;
+ break;
+ case APP:
+ // dumpProtoAppLocked will handle this.
+ continue;
+ case USER:
+ n = SystemProto.PowerUseItem.USER;
+ uid = UserHandle.getUid(bs.userId, 0);
+ break;
+ case UNACCOUNTED:
+ n = SystemProto.PowerUseItem.UNACCOUNTED;
+ break;
+ case OVERCOUNTED:
+ n = SystemProto.PowerUseItem.OVERCOUNTED;
+ break;
+ case CAMERA:
+ n = SystemProto.PowerUseItem.CAMERA;
+ break;
+ case MEMORY:
+ n = SystemProto.PowerUseItem.MEMORY;
+ break;
+ }
+ token = proto.start(SystemProto.POWER_USE_ITEM);
+ proto.write(SystemProto.PowerUseItem.NAME, n);
+ proto.write(SystemProto.PowerUseItem.UID, uid);
+ proto.write(SystemProto.PowerUseItem.COMPUTED_POWER_MAH, bs.totalPowerMah);
+ proto.write(SystemProto.PowerUseItem.SHOULD_HIDE, bs.shouldHide);
+ proto.write(SystemProto.PowerUseItem.SCREEN_POWER_MAH, bs.screenPowerMah);
+ proto.write(SystemProto.PowerUseItem.PROPORTIONAL_SMEAR_MAH,
+ bs.proportionalSmearMah);
+ proto.end(token);
+ }
+ }
+
+ // Power use summary (POWER_USE_SUMMARY_DATA)
+ token = proto.start(SystemProto.POWER_USE_SUMMARY);
+ proto.write(SystemProto.PowerUseSummary.BATTERY_CAPACITY_MAH,
+ helper.getPowerProfile().getBatteryCapacity());
+ proto.write(SystemProto.PowerUseSummary.COMPUTED_POWER_MAH, helper.getComputedPower());
+ proto.write(SystemProto.PowerUseSummary.MIN_DRAINED_POWER_MAH, helper.getMinDrainedPower());
+ proto.write(SystemProto.PowerUseSummary.MAX_DRAINED_POWER_MAH, helper.getMaxDrainedPower());
+ proto.end(token);
+
+ // RPM stats (RESOURCE_POWER_MANAGER_DATA)
+ final Map<String, ? extends Timer> rpmStats = getRpmStats();
+ final Map<String, ? extends Timer> screenOffRpmStats = getScreenOffRpmStats();
+ for (Map.Entry<String, ? extends Timer> ent : rpmStats.entrySet()) {
+ token = proto.start(SystemProto.RESOURCE_POWER_MANAGER);
+ proto.write(SystemProto.ResourcePowerManager.NAME, ent.getKey());
+ dumpTimer(proto, SystemProto.ResourcePowerManager.TOTAL,
+ ent.getValue(), rawRealtimeUs, which);
+ dumpTimer(proto, SystemProto.ResourcePowerManager.SCREEN_OFF,
+ screenOffRpmStats.get(ent.getKey()), rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Screen brightness (SCREEN_BRIGHTNESS_DATA)
+ for (int i = 0; i < NUM_SCREEN_BRIGHTNESS_BINS; ++i) {
+ token = proto.start(SystemProto.SCREEN_BRIGHTNESS);
+ proto.write(SystemProto.ScreenBrightness.NAME, i);
+ dumpTimer(proto, SystemProto.ScreenBrightness.TOTAL, getScreenBrightnessTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Signal scanning time (SIGNAL_SCANNING_TIME_DATA)
+ dumpTimer(proto, SystemProto.SIGNAL_SCANNING, getPhoneSignalScanningTimer(), rawRealtimeUs,
+ which);
+
+ // Phone signal strength (SIGNAL_STRENGTH_TIME_DATA and SIGNAL_STRENGTH_COUNT_DATA)
+ for (int i = 0; i < SignalStrength.NUM_SIGNAL_STRENGTH_BINS; ++i) {
+ token = proto.start(SystemProto.PHONE_SIGNAL_STRENGTH);
+ proto.write(SystemProto.PhoneSignalStrength.NAME, i);
+ dumpTimer(proto, SystemProto.PhoneSignalStrength.TOTAL, getPhoneSignalStrengthTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Wakeup reasons (WAKEUP_REASON_DATA)
+ final Map<String, ? extends Timer> wakeupReasons = getWakeupReasonStats();
+ for (Map.Entry<String, ? extends Timer> ent : wakeupReasons.entrySet()) {
+ token = proto.start(SystemProto.WAKEUP_REASON);
+ proto.write(SystemProto.WakeupReason.NAME, ent.getKey());
+ dumpTimer(proto, SystemProto.WakeupReason.TOTAL, ent.getValue(), rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Wifi signal strength (WIFI_SIGNAL_STRENGTH_TIME_DATA and WIFI_SIGNAL_STRENGTH_COUNT_DATA)
+ for (int i = 0; i < NUM_WIFI_SIGNAL_STRENGTH_BINS; ++i) {
+ token = proto.start(SystemProto.WIFI_SIGNAL_STRENGTH);
+ proto.write(SystemProto.WifiSignalStrength.NAME, i);
+ dumpTimer(proto, SystemProto.WifiSignalStrength.TOTAL, getWifiSignalStrengthTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Wifi state (WIFI_STATE_TIME_DATA and WIFI_STATE_COUNT_DATA)
+ for (int i = 0; i < NUM_WIFI_STATES; ++i) {
+ token = proto.start(SystemProto.WIFI_STATE);
+ proto.write(SystemProto.WifiState.NAME, i);
+ dumpTimer(proto, SystemProto.WifiState.TOTAL, getWifiStateTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ // Wifi supplicant state (WIFI_SUPPL_STATE_TIME_DATA and WIFI_SUPPL_STATE_COUNT_DATA)
+ for (int i = 0; i < NUM_WIFI_SUPPL_STATES; ++i) {
+ token = proto.start(SystemProto.WIFI_SUPPLICANT_STATE);
+ proto.write(SystemProto.WifiSupplicantState.NAME, i);
+ dumpTimer(proto, SystemProto.WifiSupplicantState.TOTAL, getWifiSupplStateTimer(i),
+ rawRealtimeUs, which);
+ proto.end(token);
+ }
+
+ proto.end(sToken);
+ }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 36fd991cc78d..dd07ddb40ad4 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -681,17 +681,17 @@ public class BatteryStatsImpl extends BatteryStats {
}
@Override
- public long getMahDischarge(int which) {
+ public long getUahDischarge(int which) {
return mDischargeCounter.getCountLocked(which);
}
@Override
- public long getMahDischargeScreenOff(int which) {
+ public long getUahDischargeScreenOff(int which) {
return mDischargeScreenOffCounter.getCountLocked(which);
}
@Override
- public long getMahDischargeScreenDoze(int which) {
+ public long getUahDischargeScreenDoze(int which) {
return mDischargeScreenDozeCounter.getCountLocked(which);
}
@@ -3588,7 +3588,7 @@ public class BatteryStatsImpl extends BatteryStats {
public void updateTimeBasesLocked(boolean unplugged, int screenState, long uptime,
long realtime) {
- final boolean screenOff = isScreenOff(screenState) || isScreenDoze(screenState);
+ final boolean screenOff = !isScreenOn(screenState);
final boolean updateOnBatteryTimeBase = unplugged != mOnBatteryTimeBase.isRunning();
final boolean updateOnBatteryScreenOffTimeBase =
(unplugged && screenOff) != mOnBatteryScreenOffTimeBase.isRunning();
@@ -5427,6 +5427,10 @@ public class BatteryStatsImpl extends BatteryStats {
elapsedRealtimeUs, which);
}
+ @Override public Timer getScreenBrightnessTimer(int brightnessBin) {
+ return mScreenBrightnessTimer[brightnessBin];
+ }
+
@Override public long getInteractiveTime(long elapsedRealtimeUs, int which) {
return mInteractiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
}
@@ -5520,10 +5524,18 @@ public class BatteryStatsImpl extends BatteryStats {
elapsedRealtimeUs, which);
}
+ @Override public Timer getPhoneSignalScanningTimer() {
+ return mPhoneSignalScanningTimer;
+ }
+
@Override public int getPhoneSignalStrengthCount(int strengthBin, int which) {
return mPhoneSignalStrengthsTimer[strengthBin].getCountLocked(which);
}
+ @Override public Timer getPhoneSignalStrengthTimer(int strengthBin) {
+ return mPhoneSignalStrengthsTimer[strengthBin];
+ }
+
@Override public long getPhoneDataConnectionTime(int dataType,
long elapsedRealtimeUs, int which) {
return mPhoneDataConnectionsTimer[dataType].getTotalTimeLocked(
@@ -5534,6 +5546,10 @@ public class BatteryStatsImpl extends BatteryStats {
return mPhoneDataConnectionsTimer[dataType].getCountLocked(which);
}
+ @Override public Timer getPhoneDataConnectionTimer(int dataType) {
+ return mPhoneDataConnectionsTimer[dataType];
+ }
+
@Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
}
@@ -5572,6 +5588,10 @@ public class BatteryStatsImpl extends BatteryStats {
return mWifiStateTimer[wifiState].getCountLocked(which);
}
+ @Override public Timer getWifiStateTimer(int wifiState) {
+ return mWifiStateTimer[wifiState];
+ }
+
@Override public long getWifiSupplStateTime(int state,
long elapsedRealtimeUs, int which) {
return mWifiSupplStateTimer[state].getTotalTimeLocked(
@@ -5582,6 +5602,10 @@ public class BatteryStatsImpl extends BatteryStats {
return mWifiSupplStateTimer[state].getCountLocked(which);
}
+ @Override public Timer getWifiSupplStateTimer(int state) {
+ return mWifiSupplStateTimer[state];
+ }
+
@Override public long getWifiSignalStrengthTime(int strengthBin,
long elapsedRealtimeUs, int which) {
return mWifiSignalStrengthsTimer[strengthBin].getTotalTimeLocked(
@@ -5592,6 +5616,10 @@ public class BatteryStatsImpl extends BatteryStats {
return mWifiSignalStrengthsTimer[strengthBin].getCountLocked(which);
}
+ @Override public Timer getWifiSignalStrengthTimer(int strengthBin) {
+ return mWifiSignalStrengthsTimer[strengthBin];
+ }
+
@Override
public ControllerActivityCounter getBluetoothControllerActivity() {
return mBluetoothActivity;
@@ -9463,7 +9491,7 @@ public class BatteryStatsImpl extends BatteryStats {
}
public boolean isScreenOn(int state) {
- return state == Display.STATE_ON;
+ return state == Display.STATE_ON || state == Display.STATE_VR;
}
public boolean isScreenOff(int state) {
@@ -12791,7 +12819,7 @@ public class BatteryStatsImpl extends BatteryStats {
mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
mMobileRadioActiveTimer = new StopwatchTimer(mClocks, null, -400, null,
mOnBatteryTimeBase, in);
- mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
+ mMobileRadioActivePerAppTimer = new StopwatchTimer(mClocks, null, -401, null,
mOnBatteryTimeBase, in);
mMobileRadioActiveAdjustedTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
mMobileRadioActiveUnknownTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
diff --git a/core/jni/eventlog_helper.h b/core/jni/eventlog_helper.h
index 1101b837b589..3a05195ebc9e 100644
--- a/core/jni/eventlog_helper.h
+++ b/core/jni/eventlog_helper.h
@@ -17,6 +17,8 @@
#ifndef FRAMEWORKS_BASE_CORE_JNI_EVENTLOG_HELPER_H_
#define FRAMEWORKS_BASE_CORE_JNI_EVENTLOG_HELPER_H_
+#include <memory>
+
#include <fcntl.h>
#include <android-base/macros.h>
@@ -26,6 +28,8 @@
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>
+#include <nativehelper/ScopedPrimitiveArray.h>
+#include <nativehelper/ScopedUtfChars.h>
#include "core_jni_helpers.h"
#include "jni.h"
@@ -91,20 +95,14 @@ public:
android_log_event_list ctx(tag);
// Don't throw NPE -- I feel like it's sort of mean for a logging function
// to be all crashy if you pass in NULL -- but make the NULL value explicit.
- if (value != NULL) {
- const char *str = env->GetStringUTFChars(value, NULL);
- ctx << str;
- env->ReleaseStringUTFChars(value, str);
- } else {
- ctx << "NULL";
- }
+ ctx << (value != nullptr ? ScopedUtfChars(env, value).c_str() : "NULL");
return ctx.write(LogID);
}
static jint writeEventArray(JNIEnv* env, jobject clazz ATTRIBUTE_UNUSED, jint tag,
jobjectArray value) {
android_log_event_list ctx(tag);
- if (value == NULL) {
+ if (value == nullptr) {
ctx << "[NULL]";
return ctx.write(LogID);
}
@@ -112,26 +110,23 @@ public:
jsize copied = 0, num = env->GetArrayLength(value);
for (; copied < num && copied < 255; ++copied) {
if (ctx.status()) break;
- jobject item = env->GetObjectArrayElement(value, copied);
- if (item == NULL) {
+ ScopedLocalRef<jobject> item(env, env->GetObjectArrayElement(value, copied));
+ if (item == nullptr) {
ctx << "NULL";
- } else if (env->IsInstanceOf(item, gStringClass)) {
- const char *str = env->GetStringUTFChars((jstring) item, NULL);
- ctx << str;
- env->ReleaseStringUTFChars((jstring) item, str);
- } else if (env->IsInstanceOf(item, gIntegerClass)) {
- ctx << (int32_t)env->GetIntField(item, gIntegerValueID);
- } else if (env->IsInstanceOf(item, gLongClass)) {
- ctx << (int64_t)env->GetLongField(item, gLongValueID);
- } else if (env->IsInstanceOf(item, gFloatClass)) {
- ctx << (float)env->GetFloatField(item, gFloatValueID);
+ } else if (env->IsInstanceOf(item.get(), gStringClass)) {
+ ctx << ScopedUtfChars(env, (jstring) item.get()).c_str();
+ } else if (env->IsInstanceOf(item.get(), gIntegerClass)) {
+ ctx << (int32_t)env->GetIntField(item.get(), gIntegerValueID);
+ } else if (env->IsInstanceOf(item.get(), gLongClass)) {
+ ctx << (int64_t)env->GetLongField(item.get(), gLongValueID);
+ } else if (env->IsInstanceOf(item.get(), gFloatClass)) {
+ ctx << (float)env->GetFloatField(item.get(), gFloatValueID);
} else {
jniThrowException(env,
"java/lang/IllegalArgumentException",
"Invalid payload item type");
return -1;
}
- env->DeleteLocalRef(item);
}
return ctx.write(LogID);
}
@@ -140,39 +135,37 @@ public:
readEvents(env, loggerMode, nullptr, startTime, out);
}
- static void readEvents(JNIEnv* env, int loggerMode, jintArray tags, jlong startTime,
+ static void readEvents(JNIEnv* env, int loggerMode, jintArray jTags, jlong startTime,
jobject out) {
- struct logger_list *logger_list;
+ std::unique_ptr<struct logger_list, decltype(&android_logger_list_close)> logger_list(
+ nullptr, android_logger_list_close);
if (startTime) {
- logger_list = android_logger_list_alloc_time(loggerMode,
- log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0);
+ logger_list.reset(android_logger_list_alloc_time(loggerMode,
+ log_time(startTime / NS_PER_SEC, startTime % NS_PER_SEC), 0));
} else {
- logger_list = android_logger_list_alloc(loggerMode, 0, 0);
+ logger_list.reset(android_logger_list_alloc(loggerMode, 0, 0));
}
if (!logger_list) {
jniThrowIOException(env, errno);
return;
}
- if (!android_logger_open(logger_list, LogID)) {
+ if (!android_logger_open(logger_list.get(), LogID)) {
jniThrowIOException(env, errno);
- android_logger_list_free(logger_list);
return;
}
- jsize tagLength = 0;
- jint *tagValues = nullptr;
- if (tags != nullptr) {
- tagLength = env->GetArrayLength(tags);
- tagValues = env->GetIntArrayElements(tags, NULL);
+ ScopedIntArrayRO tags(env);
+ if (jTags != nullptr) {
+ tags.reset(jTags);
}
while (1) {
log_msg log_msg;
- int ret = android_logger_list_read(logger_list, &log_msg);
+ int ret = android_logger_list_read(logger_list.get(), &log_msg);
if (ret == 0) {
- break;
+ return;
}
if (ret < 0) {
if (ret == -EINTR) {
@@ -183,7 +176,7 @@ public:
} else if (ret != -EAGAIN) {
jniThrowIOException(env, -ret); // Will throw on return
}
- break;
+ return;
}
if (log_msg.id() != LogID) {
@@ -192,10 +185,10 @@ public:
int32_t tag = * (int32_t *) log_msg.msg();
- if (tags != nullptr) {
+ if (jTags != nullptr) {
bool found = false;
- for (int i = 0; !found && i < tagLength; ++i) {
- found = (tag == tagValues[i]);
+ for (size_t i = 0; !found && i < tags.size(); ++i) {
+ found = (tag == tags[i]);
}
if (!found) {
continue;
@@ -203,33 +196,27 @@ public:
}
jsize len = ret;
- jbyteArray array = env->NewByteArray(len);
- if (array == NULL) {
- break;
+ ScopedLocalRef<jbyteArray> array(env, env->NewByteArray(len));
+ if (array == nullptr) {
+ return;
}
- jbyte *bytes = env->GetByteArrayElements(array, NULL);
- memcpy(bytes, log_msg.buf, len);
- env->ReleaseByteArrayElements(array, bytes, 0);
+ {
+ ScopedByteArrayRW bytes(env, array.get());
+ memcpy(bytes.get(), log_msg.buf, len);
+ }
- jobject event = env->NewObject(gEventClass, gEventInitID, array);
- if (event == NULL) {
- break;
+ ScopedLocalRef<jobject> event(env,
+ env->NewObject(gEventClass, gEventInitID, array.get()));
+ if (event == nullptr) {
+ return;
}
- env->CallBooleanMethod(out, gCollectionAddID, event);
- env->DeleteLocalRef(event);
- env->DeleteLocalRef(array);
+ env->CallBooleanMethod(out, gCollectionAddID, event.get());
if (env->ExceptionCheck() == JNI_TRUE) {
- break;
+ return;
}
}
-
- android_logger_list_close(logger_list);
-
- if (tags != nullptr) {
- env->ReleaseIntArrayElements(tags, tagValues, 0);
- }
}
private:
diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto
index 86e31d0940db..8d850384ffe3 100644
--- a/core/proto/android/os/batterystats.proto
+++ b/core/proto/android/os/batterystats.proto
@@ -20,6 +20,8 @@ option java_multiple_files = true;
package android.os;
+import "frameworks/base/core/proto/android/telephony/signalstrength.proto";
+
message BatteryStatsProto {
int32 report_version = 1;
int64 parcel_version = 2;
@@ -55,6 +57,383 @@ message ControllerActivityProto {
}
message SystemProto {
+ message Battery {
+ // Wall clock time when the data collection started.
+ // In case of device time manually reset by users:
+ // start_clock_time_ms keeps the same value in the current collection
+ // period and changes for later collection periods.
+ int64 start_clock_time_ms = 1;
+ // #times the device has been started since start_clock_time_millis.
+ int64 start_count = 2;
+ // Total realtime duration (= SINCE_UNPLUGGED battery_realtime_millis.)
+ int64 total_realtime_ms = 3;
+ int64 total_uptime_ms = 4;
+ // Realtime duration on battery.
+ int64 battery_realtime_ms = 5;
+ // Uptime duration (i.e., not suspend).
+ // Uptime is anytime the CPUs were on. The radio and Wifi chip
+ // can be running while the CPUs are off.
+ int64 battery_uptime_ms = 6;
+ // Total realtime duration measured with screen off or dozing.
+ int64 screen_off_realtime_ms = 7;
+ // Total uptime duration measured with screen off or dozing.
+ int64 screen_off_uptime_ms = 8;
+ // Total time the screen was dozing while the device was running on battery.
+ // For historical reasons, screen_doze_duration_msec is a subset of
+ // screen_off_realtime_msec.
+ int64 screen_doze_duration_ms = 9;
+ // The estimated real battery capacity, which may be less than the declared
+ // battery capacity (for example, because of battery aging). This field is
+ // less reliable than min(max)_learned_battery_capacity_uah, use those two
+ // fields whenever possible.
+ int64 estimated_battery_capacity_mah = 10;
+ // The minimum learned battery capacity in uAh.
+ int64 min_learned_battery_capacity_uah = 11;
+ // The maximum learned battery capacity in uAh.
+ int64 max_learned_battery_capacity_uah = 12;
+ };
+ Battery battery = 1;
+
+ message BatteryDischarge {
+ // Discharged battery percentage points since the stats were last reset
+ // after charging (lower bound approximation).
+ int32 lower_bound_since_charge = 1;
+ // Upper bound approximation.
+ int32 upper_bound_since_charge = 2;
+ // Discharged points while screen is on.
+ int32 screen_on_since_charge = 3;
+ // Discharged points while screen is off.
+ int32 screen_off_since_charge = 4;
+ // Discharged points while screen was dozing. For historical reasons,
+ // screen_doze_since_charge is a subset of screen_off_since_charge.
+ int32 screen_doze_since_charge = 5;
+ // Total amount of battery discharged in mAh. This will only be non-zero for
+ // devices that report battery discharge via a coulomb counter.
+ int64 total_mah = 6;
+ // Total amount of battery discharged while the screen was off in mAh.
+ // This will only be non-zero for devices that report battery discharge
+ // via a coulomb counter.
+ int64 total_mah_screen_off = 7;
+ // Total amount of battery discharged while the screen was dozing in mAh.
+ // This will only be non-zero for devices that report battery discharge
+ // via a coulomb counter. For historical reasons, total_mah_screen_doze is
+ // a subset of total_mah_screen_off.
+ int64 total_mah_screen_doze = 8;
+ };
+ BatteryDischarge battery_discharge = 2;
+
+ oneof time_remaining {
+ // Approximation for how much time remains until the battery is fully
+ // charged. The device will print -1 if there wasn't enough data to
+ // calculate an estimate, or if the battery is currently discharging.
+ int64 charge_time_remaining_ms = 3;
+ // Approximation for how much time remains until the battery is fully
+ // discharged. The device will print -1 if there wasn't enough data to
+ // calculate an estimate, or if the battery is currently charging.
+ int64 discharge_time_remaining_ms = 4;
+ }
+
+ // BatteryLevelStep tracks data for which conditions were continuously held for
+ // the entire duration. Field for which the conditions were not consistent
+ // for the entire duration should be marked MIXED.
+ message BatteryLevelStep {
+ // How long the battery was at the current level.
+ int64 duration_ms = 1;
+ // Battery level
+ int32 level = 2;
+
+ // State of the display. A special enum is used rather than
+ // DisplayProto.State because a MIXED value needs to be in the enum, and
+ // batterystats doesn't care about all of the different display states.
+ enum DisplayState {
+ DS_MIXED = 0;
+ DS_ON = 1;
+ DS_OFF = 2;
+ DS_DOZE = 3;
+ DS_DOZE_SUSPEND = 4;
+ // Any display state error that comes through should be sent to hackbod@.
+ DS_ERROR = 5;
+ }
+ // The state of the display for the entire battery level step. MIXED is used
+ // if there were multiple states for this step.
+ DisplayState display_state = 3;
+
+ // Indicates status in power save mode.
+ enum PowerSaveMode {
+ PSM_MIXED = 0;
+ PSM_ON = 1;
+ PSM_OFF = 2;
+ }
+ // Battery Saver mode for the entire battery level step. MIXED is used
+ // if there were multiple states for this step.
+ PowerSaveMode power_save_mode = 4;
+
+ // Indicates status in idle mode.
+ enum IdleMode {
+ IM_MIXED = 0;
+ IM_ON = 2;
+ IM_OFF = 3;
+ }
+ // Doze mode for the entire battery level step. MIXED is used if there were
+ // multiple states for this step.
+ IdleMode idle_mode = 5;
+ };
+ // Battery level steps when the device was charging.
+ repeated BatteryLevelStep charge_step = 5;
+ // Battery level steps when the device was discharging.
+ repeated BatteryLevelStep discharge_step = 6;
+
+ // All CPU frequencies of the device.
+ repeated int64 cpu_frequency = 7;
+
+ message DataConnection {
+ enum Name {
+ NONE = 0;
+ GPRS = 1;
+ EDGE = 2;
+ UMTS = 3;
+ CDMA = 4;
+ EVDO_0 = 5;
+ EVDO_A = 6;
+ ONE_X_RTT = 7; // 1xRTT.
+ HSDPA = 8;
+ HSUPA = 9;
+ HSPA = 10;
+ IDEN = 11;
+ EVDO_B = 12;
+ LTE = 13;
+ EHRPD = 14;
+ HSPAP = 15;
+ OTHER = 16;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated DataConnection data_connection = 8;
+
+ ControllerActivityProto global_bluetooth_controller = 9;
+ ControllerActivityProto global_modem_controller = 10;
+ ControllerActivityProto global_wifi_controller = 11;
+
+ message GlobalNetwork {
+ // Total Bytes received on mobile connections.
+ int64 mobile_bytes_rx = 1;
+ // Total Bytes transmitted on mobile connections.
+ int64 mobile_bytes_tx = 2;
+ // Total Bytes received on wifi connections.
+ int64 wifi_bytes_rx = 3;
+ // Total Bytes transmitted on wifi connections.
+ int64 wifi_bytes_tx = 4;
+ // Total Packets received on mobile connections.
+ int64 mobile_packets_rx = 5;
+ // Total Packets transmitted on mobile connections.
+ int64 mobile_packets_tx = 6;
+ // Total Packets received on wifi connections.
+ int64 wifi_packets_rx = 7;
+ // Total Packets transmitted on wifi connections.
+ int64 wifi_packets_tx = 8;
+ // Total Bytes received on bluetooth connections.
+ int64 bt_bytes_rx = 9;
+ // Total Bytes transmitted on bluetooth connections.
+ int64 bt_bytes_tx = 10;
+ };
+ GlobalNetwork global_network = 12;
+
+ message GlobalWifi {
+ // The amount of time that wifi has been on while the device was running on
+ // battery.
+ int64 on_duration_ms = 1;
+ // The amount of time that wifi has been on and the driver has been in the
+ // running state while the device was running on battery.
+ int64 running_duration_ms = 2;
+ }
+ GlobalWifi global_wifi = 13;
+
+ // Kernel wakelock metrics are only recorded when the device is unplugged
+ // *and* the screen is off.
+ message KernelWakelock {
+ string name = 1;
+ // Kernel wakelock stats aren't apportioned across all kernel wakelocks (as
+ // app wakelocks stats are).
+ TimerProto total = 2;
+ // The kernel doesn't have the data to enable printing out current and max
+ // durations.
+ };
+ repeated KernelWakelock kernel_wakelock = 14;
+
+ message Misc {
+ int64 screen_on_duration_ms = 1;
+ int64 phone_on_duration_ms = 2;
+ int64 full_wakelock_total_duration_ms = 3;
+ // The total elapsed time that a partial wakelock was held. This duration
+ // does not double count wakelocks held at the same time.
+ int64 partial_wakelock_total_duration_ms = 4;
+ int64 mobile_radio_active_duration_ms = 5;
+ // The time that is the difference between the mobile radio time we saw
+ // based on the elapsed timestamp when going down vs. the given time stamp
+ // from the radio.
+ int64 mobile_radio_active_adjusted_time_ms = 6;
+ int32 mobile_radio_active_count = 7;
+ // The amount of time that the mobile network has been active (in a high
+ // power state) but not being able to blame on an app.
+ int32 mobile_radio_active_unknown_duration_ms = 8;
+ // Total amount of time the device was in the interactive state.
+ int64 interactive_duration_ms = 9;
+ int64 battery_saver_mode_enabled_duration_ms = 10;
+ int32 num_connectivity_changes = 11;
+ // Amount of time the device was in deep Doze.
+ int64 deep_doze_enabled_duration_ms = 12;
+ // How many times the device went into deep Doze mode.
+ int32 deep_doze_count = 13;
+ // Amount of time the device was idling in deep Doze. Idling time
+ // encompasses "doze" time and the maintenance windows that allow apps to
+ // operate.
+ int64 deep_doze_idling_duration_ms = 14;
+ // How many times the device idling for deep Doze mode.
+ int32 deep_doze_idling_count = 15;
+ int64 longest_deep_doze_duration_ms = 16;
+ // Amount of time the device was in Doze Light.
+ int64 light_doze_enabled_duration_ms = 17;
+ // How many times the device went into Doze Light mode.
+ int32 light_doze_count = 18;
+ // Amount of time the device was idling in Doze Light. Idling time
+ // encompasses "doze" time and the maintenance windows that allow apps to
+ // operate.
+ int64 light_doze_idling_duration_ms = 19;
+ // How many times the device idling for Doze Light mode.
+ int32 light_doze_idling_count = 20;
+ int64 longest_light_doze_duration_ms = 21;
+ }
+ Misc misc = 15;
+
+ message PhoneSignalStrength {
+ android.telephony.SignalStrengthProto.StrengthName name = 1;
+ TimerProto total = 2;
+ };
+ repeated PhoneSignalStrength phone_signal_strength = 16;
+
+ message PowerUseItem {
+ enum Sipper {
+ UNKNOWN_SIPPER = 0;
+ IDLE = 1;
+ CELL = 2;
+ PHONE = 3;
+ WIFI = 4;
+ BLUETOOTH = 5;
+ FLASHLIGHT = 6;
+ SCREEN = 7;
+ USER = 8;
+ UNACCOUNTED = 9;
+ OVERCOUNTED = 10;
+ CAMERA = 11;
+ MEMORY = 12;
+ };
+ Sipper name = 1;
+ // UID, only valid for the USER sipper.
+ int32 uid = 2;
+ // Estimated power use in mAh.
+ double computed_power_mah = 3;
+ // Starting in Oreo, Battery Settings has two modes to display the battery
+ // info. The first is "app usage list". In this mode, items with should_hide
+ // enabled are hidden.
+ bool should_hide = 4;
+ // Smeared power from screen usage. Screen usage power is split and smeared
+ // among apps, based on activity time.
+ double screen_power_mah = 5;
+ // Smeared power using proportional method. Power usage from hidden sippers
+ // is smeared to all apps proportionally (except for screen usage).
+ double proportional_smear_mah = 6;
+ };
+ repeated PowerUseItem power_use_item = 17;
+
+ message PowerUseSummary {
+ double battery_capacity_mah = 1;
+ double computed_power_mah = 2;
+ // Lower bound of actual power drained.
+ double min_drained_power_mah = 3;
+ // Upper bound of actual power drained.
+ double max_drained_power_mah = 4;
+ };
+ PowerUseSummary power_use_summary = 18;
+
+ message ResourcePowerManager {
+ string name = 1;
+ TimerProto total = 2;
+ TimerProto screen_off = 3;
+ }
+ ResourcePowerManager resource_power_manager = 19;
+
+ message ScreenBrightness {
+ enum Name {
+ DARK = 0; // Not screen-off.
+ DIM = 1;
+ MEDIUM = 2;
+ LIGHT = 3;
+ BRIGHT = 4;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated ScreenBrightness screen_brightness = 20;
+
+ // Duration and number of times trying to acquire a signal
+ TimerProto signal_scanning = 21;
+
+ message WakeupReason {
+ string name = 1;
+ TimerProto total = 2;
+ };
+ repeated WakeupReason wakeup_reason = 22;
+
+ message WifiSignalStrength {
+ enum Name {
+ NONE = 0;
+ POOR = 1;
+ MODERATE = 2;
+ GOOD = 3;
+ GREAT = 4;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated WifiSignalStrength wifi_signal_strength = 23;
+
+ message WifiState {
+ enum Name {
+ OFF = 0;
+ OFF_SCANNING = 1;
+ ON_NO_NETWORKS = 2;
+ ON_DISCONNECTED = 3;
+ ON_CONNECTED_STA = 4;
+ ON_CONNECTED_P2P = 5;
+ ON_CONNECTED_STA_P2P = 6;
+ SOFT_AP = 7;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated WifiState wifi_state = 24;
+
+ message WifiSupplicantState {
+ enum Name {
+ INVALID = 0;
+ DISCONNECTED = 1;
+ INTERFACE_DISABLED = 2;
+ INACTIVE = 3;
+ SCANNING = 4;
+ AUTHENTICATING = 5;
+ ASSOCIATING = 6;
+ ASSOCIATED = 7;
+ FOUR_WAY_HANDSHAKE = 8;
+ GROUP_HANDSHAKE = 9;
+ COMPLETED = 10;
+ DORMANT = 11;
+ UNINITIALIZED = 12;
+ };
+ Name name = 1;
+ TimerProto total = 2;
+ };
+ repeated WifiSupplicantState wifi_supplicant_state = 25;
}
message TimerProto {
diff --git a/core/proto/android/telephony/signalstrength.proto b/core/proto/android/telephony/signalstrength.proto
new file mode 100644
index 000000000000..ff230cba6a57
--- /dev/null
+++ b/core/proto/android/telephony/signalstrength.proto
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto3";
+
+option java_package = "android.telephony";
+option java_multiple_files = true;
+
+package android.telephony;
+
+/**
+ * An android.telephony.SignalStrength object.
+ */
+message SignalStrengthProto {
+ enum StrengthName {
+ SIGNAL_STRENGTH_NONE_OR_UNKNOWN = 0;
+ SIGNAL_STRENGTH_POOR = 1;
+ SIGNAL_STRENGTH_MODERATE = 2;
+ SIGNAL_STRENGTH_GOOD = 3;
+ SIGNAL_STRENGTH_GREAT = 4;
+ }
+}
diff --git a/core/res/res/values-mcc001-mnc01/strings.xml b/core/res/res/values-mcc001-mnc01/strings.xml
new file mode 100644
index 000000000000..96af975b50b5
--- /dev/null
+++ b/core/res/res/values-mcc001-mnc01/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc030/strings.xml b/core/res/res/values-mcc310-mnc030/strings.xml
index a3fea29070f5..6a404d5cee5f 100644
--- a/core/res/res/values-mcc310-mnc030/strings.xml
+++ b/core/res/res/values-mcc310-mnc030/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc150/strings.xml b/core/res/res/values-mcc310-mnc150/strings.xml
new file mode 100644
index 000000000000..96af975b50b5
--- /dev/null
+++ b/core/res/res/values-mcc310-mnc150/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
+</resources>
diff --git a/core/res/res/values-mcc310-mnc170/strings.xml b/core/res/res/values-mcc310-mnc170/strings.xml
index a3fea29070f5..6a404d5cee5f 100644
--- a/core/res/res/values-mcc310-mnc170/strings.xml
+++ b/core/res/res/values-mcc310-mnc170/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc280/strings.xml b/core/res/res/values-mcc310-mnc280/strings.xml
index a3fea29070f5..6a404d5cee5f 100644
--- a/core/res/res/values-mcc310-mnc280/strings.xml
+++ b/core/res/res/values-mcc310-mnc280/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc410/strings.xml b/core/res/res/values-mcc310-mnc410/strings.xml
index a3fea29070f5..6a404d5cee5f 100644
--- a/core/res/res/values-mcc310-mnc410/strings.xml
+++ b/core/res/res/values-mcc310-mnc410/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc560/strings.xml b/core/res/res/values-mcc310-mnc560/strings.xml
index a3fea29070f5..6a404d5cee5f 100644
--- a/core/res/res/values-mcc310-mnc560/strings.xml
+++ b/core/res/res/values-mcc310-mnc560/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc310-mnc950/strings.xml b/core/res/res/values-mcc310-mnc950/strings.xml
index a3fea29070f5..6a404d5cee5f 100644
--- a/core/res/res/values-mcc310-mnc950/strings.xml
+++ b/core/res/res/values-mcc310-mnc950/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc311-mnc180/strings.xml b/core/res/res/values-mcc311-mnc180/strings.xml
index a3fea29070f5..6a404d5cee5f 100644
--- a/core/res/res/values-mcc311-mnc180/strings.xml
+++ b/core/res/res/values-mcc311-mnc180/strings.xml
@@ -20,4 +20,5 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="mmcc_imsi_unknown_in_hlr">SIM not provisioned MM#2</string>
<string name="mmcc_illegal_ms">SIM not allowed MM#3</string>
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
</resources>
diff --git a/core/res/res/values-mcc312-mnc670/strings.xml b/core/res/res/values-mcc312-mnc670/strings.xml
new file mode 100644
index 000000000000..96af975b50b5
--- /dev/null
+++ b/core/res/res/values-mcc312-mnc670/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
+</resources>
diff --git a/core/res/res/values-mcc313-mnc100/strings.xml b/core/res/res/values-mcc313-mnc100/strings.xml
new file mode 100644
index 000000000000..96af975b50b5
--- /dev/null
+++ b/core/res/res/values-mcc313-mnc100/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/any/strings.xml
+**
+** Copyright 2006, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <string name="mmcc_illegal_me">Phone not allowed MM#6</string>
+</resources>
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 461d537e86f9..4e8322183a8b 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -214,7 +214,7 @@ public class BatteryStatsNoteTest extends TestCase{
assertTrue(bi.getOnBatteryScreenOffTimeBase().isRunning());
}
- /** Test BatteryStatsImpl.noteScreenStateLocked. */
+ /** Test BatteryStatsImpl.noteScreenStateLocked sets timebases and screen states correctly. */
@SmallTest
public void testNoteScreenStateLocked() throws Exception {
final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
@@ -233,4 +233,52 @@ public class BatteryStatsNoteTest extends TestCase{
assertEquals(bi.getScreenState(), Display.STATE_OFF);
}
+ /** Test BatteryStatsImpl.noteScreenStateLocked updates timers correctly.
+ *
+ * Unknown and doze should both be subset of off state
+ *
+ * Timeline 0----100----200----310----400------------1000
+ * Unknown -------
+ * On -------
+ * Off ------- ----------------------
+ * Doze ----------------
+ */
+ @SmallTest
+ public void testNoteScreenStateTimersLocked() throws Exception {
+ final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+ MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+
+ clocks.realtime = clocks.uptime = 100;
+ // Device startup, setOnBatteryLocked calls updateTimebases
+ bi.updateTimeBasesLocked(true, Display.STATE_UNKNOWN, 100_000, 100_000);
+ // Turn on display at 200us
+ clocks.realtime = clocks.uptime = 200;
+ bi.noteScreenStateLocked(Display.STATE_ON);
+ assertEquals(150_000, bi.computeBatteryRealtime(250_000, STATS_SINCE_CHARGED));
+ assertEquals(100_000, bi.computeBatteryScreenOffRealtime(250_000, STATS_SINCE_CHARGED));
+ assertEquals(50_000, bi.getScreenOnTime(250_000, STATS_SINCE_CHARGED));
+ assertEquals(0, bi.getScreenDozeTime(250_000, STATS_SINCE_CHARGED));
+
+ clocks.realtime = clocks.uptime = 310;
+ bi.noteScreenStateLocked(Display.STATE_OFF);
+ assertEquals(250_000, bi.computeBatteryRealtime(350_000, STATS_SINCE_CHARGED));
+ assertEquals(140_000, bi.computeBatteryScreenOffRealtime(350_000, STATS_SINCE_CHARGED));
+ assertEquals(110_000, bi.getScreenOnTime(350_000, STATS_SINCE_CHARGED));
+ assertEquals(0, bi.getScreenDozeTime(350_000, STATS_SINCE_CHARGED));
+
+ clocks.realtime = clocks.uptime = 400;
+ bi.noteScreenStateLocked(Display.STATE_DOZE);
+ assertEquals(400_000, bi.computeBatteryRealtime(500_000, STATS_SINCE_CHARGED));
+ assertEquals(290_000, bi.computeBatteryScreenOffRealtime(500_000, STATS_SINCE_CHARGED));
+ assertEquals(110_000, bi.getScreenOnTime(500_000, STATS_SINCE_CHARGED));
+ assertEquals(100_000, bi.getScreenDozeTime(500_000, STATS_SINCE_CHARGED));
+
+ clocks.realtime = clocks.uptime = 1000;
+ bi.noteScreenStateLocked(Display.STATE_OFF);
+ assertEquals(1400_000, bi.computeBatteryRealtime(1500_000, STATS_SINCE_CHARGED));
+ assertEquals(1290_000, bi.computeBatteryScreenOffRealtime(1500_000, STATS_SINCE_CHARGED));
+ assertEquals(110_000, bi.getScreenOnTime(1500_000, STATS_SINCE_CHARGED));
+ assertEquals(600_000, bi.getScreenDozeTime(1500_000, STATS_SINCE_CHARGED));
+ }
+
}
diff --git a/libs/protoutil/Android.mk b/libs/protoutil/Android.mk
index a5348169513f..2a2b087dc032 100644
--- a/libs/protoutil/Android.mk
+++ b/libs/protoutil/Android.mk
@@ -22,15 +22,15 @@ LOCAL_CFLAGS := \
-Wall -Werror -Wno-missing-field-initializers -Wno-unused-variable -Wunused-parameter
LOCAL_SHARED_LIBRARIES := \
- libbinder \
+ libcutils \
liblog \
- libutils
LOCAL_C_INCLUDES := \
$(LOCAL_PATH)/include
LOCAL_SRC_FILES := \
src/EncodedBuffer.cpp \
+ src/ProtoOutputStream.cpp \
src/protobuf.cpp \
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
diff --git a/libs/protoutil/include/android/util/EncodedBuffer.h b/libs/protoutil/include/android/util/EncodedBuffer.h
index cf096091c055..e568e4cf02fc 100644
--- a/libs/protoutil/include/android/util/EncodedBuffer.h
+++ b/libs/protoutil/include/android/util/EncodedBuffer.h
@@ -52,10 +52,10 @@ public:
size_t index() const;
size_t offset() const;
- void move(size_t amt);
- inline void move() { move(1); };
+ Pointer* move(size_t amt);
+ inline Pointer* move() { return move(1); };
+ Pointer* rewind();
- void rewind();
Pointer copy() const;
private:
@@ -88,15 +88,71 @@ public:
size_t currentToWrite();
/**
- * Write a varint into a vector. Return the size of the varint.
+ * Write a single byte to the buffer.
*/
- size_t writeRawVarint(uint32_t val);
+ void writeRawByte(uint8_t val);
+
+ /**
+ * Write a varint32 into the buffer. Return the size of the varint.
+ */
+ size_t writeRawVarint32(uint32_t val);
+
+ /**
+ * Write a varint64 into the buffer. Return the size of the varint.
+ */
+ size_t writeRawVarint64(uint64_t val);
+
+ /**
+ * Write Fixed32 into the buffer.
+ */
+ void writeRawFixed32(uint32_t val);
+
+ /**
+ * Write Fixed64 into the buffer.
+ */
+ void writeRawFixed64(uint64_t val);
/**
* Write a protobuf header. Return the size of the header.
*/
size_t writeHeader(uint32_t fieldId, uint8_t wireType);
+ /********************************* Edit APIs ************************************************/
+ /**
+ * Returns the edit pointer.
+ */
+ Pointer* ep();
+
+ /**
+ * Read a single byte at ep, and move ep to next byte;
+ */
+ uint8_t readRawByte();
+
+ /**
+ * Read varint starting at ep, ep will move to pos of next byte.
+ */
+ uint64_t readRawVarint();
+
+ /**
+ * Read 4 bytes starting at ep, ep will move to pos of next byte.
+ */
+ uint32_t readRawFixed32();
+
+ /**
+ * Read 8 bytes starting at ep, ep will move to pos of next byte.
+ */
+ uint64_t readRawFixed64();
+
+ /**
+ * Edit 4 bytes starting at pos.
+ */
+ void editRawFixed32(size_t pos, uint32_t val);
+
+ /**
+ * Copy _size_ bytes of data starting at __srcPos__ to wp.
+ */
+ void copy(size_t srcPos, size_t size);
+
/********************************* Read APIs ************************************************/
class iterator;
friend class iterator;
@@ -141,9 +197,8 @@ public:
/**
* Read varint from iterator, the iterator will point to next available byte.
- * Return the number of bytes of the varint.
*/
- uint32_t readRawVarint();
+ uint64_t readRawVarint();
private:
const EncodedBuffer& mData;
@@ -160,6 +215,7 @@ private:
vector<uint8_t*> mBuffers;
Pointer mWp;
+ Pointer mEp;
inline uint8_t* at(const Pointer& p) const; // helper function to get value
};
@@ -167,4 +223,5 @@ private:
} // util
} // android
-#endif // ANDROID_UTIL_ENCODED_BUFFER_H \ No newline at end of file
+#endif // ANDROID_UTIL_ENCODED_BUFFER_H
+
diff --git a/libs/protoutil/include/android/util/ProtoOutputStream.h b/libs/protoutil/include/android/util/ProtoOutputStream.h
new file mode 100644
index 000000000000..49ec169b3e5c
--- /dev/null
+++ b/libs/protoutil/include/android/util/ProtoOutputStream.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_UTIL_PROTOOUTPUT_STREAM_H
+#define ANDROID_UTIL_PROTOOUTPUT_STREAM_H
+
+#include <android/util/EncodedBuffer.h>
+
+#include <stdint.h>
+#include <string>
+
+namespace android {
+namespace util {
+
+/**
+ * Class to write to a protobuf stream.
+ *
+ * Each write method takes an ID code from the protoc generated classes
+ * and the value to write. To make a nested object, call start
+ * and then end when you are done.
+ *
+ * See the java version implementation (ProtoOutputStream.java) for more infos.
+ */
+class ProtoOutputStream
+{
+public:
+ ProtoOutputStream(int fd);
+ ~ProtoOutputStream();
+
+ /**
+ * Write APIs for dumping protobuf data. Returns true if the write succeeds.
+ */
+ bool write(uint64_t fieldId, double val);
+ bool write(uint64_t fieldId, float val);
+ bool write(uint64_t fieldId, int val);
+ bool write(uint64_t fieldId, long long val);
+ bool write(uint64_t fieldId, bool val);
+ bool write(uint64_t fieldId, std::string val);
+ bool write(uint64_t fieldId, const char* val);
+
+ /**
+ * Starts a sub-message write session.
+ * Returns a token of this write session.
+ * Must call end(token) when finish write this sub-message.
+ */
+ long long start(uint64_t fieldId);
+ void end(long long token);
+
+ /**
+ * Flushes the protobuf data out.
+ */
+ bool flush();
+
+private:
+ EncodedBuffer mBuffer;
+ int mFd;
+ size_t mCopyBegin;
+ bool mCompact;
+ int mDepth;
+ int mObjectId;
+ long long mExpectedObjectToken;
+
+ inline void writeDoubleImpl(uint32_t id, double val);
+ inline void writeFloatImpl(uint32_t id, float val);
+ inline void writeInt64Impl(uint32_t id, long long val);
+ inline void writeInt32Impl(uint32_t id, int val);
+ inline void writeUint64Impl(uint32_t id, uint64_t val);
+ inline void writeUint32Impl(uint32_t id, uint32_t val);
+ inline void writeFixed64Impl(uint32_t id, uint64_t val);
+ inline void writeFixed32Impl(uint32_t id, uint32_t val);
+ inline void writeSFixed64Impl(uint32_t id, long long val);
+ inline void writeSFixed32Impl(uint32_t id, int val);
+ inline void writeZigzagInt64Impl(uint32_t id, long long val);
+ inline void writeZigzagInt32Impl(uint32_t id, int val);
+ inline void writeEnumImpl(uint32_t id, int val);
+ inline void writeBoolImpl(uint32_t id, bool val);
+ inline void writeUtf8StringImpl(uint32_t id, const char* val, size_t size);
+
+ bool compact();
+ size_t editEncodedSize(size_t rawSize);
+ bool compactSize(size_t rawSize);
+};
+
+}
+}
+
+#endif // ANDROID_UTIL_PROTOOUTPUT_STREAM_H \ No newline at end of file
diff --git a/libs/protoutil/include/android/util/protobuf.h b/libs/protoutil/include/android/util/protobuf.h
index f4e8d092ba52..ca45e263b20e 100644
--- a/libs/protoutil/include/android/util/protobuf.h
+++ b/libs/protoutil/include/android/util/protobuf.h
@@ -24,6 +24,9 @@ namespace util {
using namespace std;
+const int FIELD_ID_SHIFT = 3;
+const uint8_t WIRE_TYPE_MASK = (1 << FIELD_ID_SHIFT) - 1;
+
const uint8_t WIRE_TYPE_VARINT = 0;
const uint8_t WIRE_TYPE_FIXED64 = 1;
const uint8_t WIRE_TYPE_LENGTH_DELIMITED = 2;
@@ -35,16 +38,20 @@ const uint8_t WIRE_TYPE_FIXED32 = 5;
uint8_t read_wire_type(uint32_t varint);
/**
- * read field id from varint, it is varint >> 3;
+ * Read field id from varint, it is varint >> 3;
*/
uint32_t read_field_id(uint32_t varint);
/**
+ * Get the size of a varint.
+ */
+size_t get_varint_size(uint64_t varint);
+
+/**
* Write a varint into the buffer. Return the next position to write at.
- * There must be 10 bytes in the buffer. The same as
- * EncodedBuffer.writeRawVarint32
+ * There must be 10 bytes in the buffer.
*/
-uint8_t* write_raw_varint(uint8_t* buf, uint32_t val);
+uint8_t* write_raw_varint(uint8_t* buf, uint64_t val);
/**
* Write a protobuf WIRE_TYPE_LENGTH_DELIMITED header. Return the next position
diff --git a/libs/protoutil/src/EncodedBuffer.cpp b/libs/protoutil/src/EncodedBuffer.cpp
index 84dc5b6d7852..435ae8836217 100644
--- a/libs/protoutil/src/EncodedBuffer.cpp
+++ b/libs/protoutil/src/EncodedBuffer.cpp
@@ -15,6 +15,7 @@
*/
#include <android/util/EncodedBuffer.h>
+#include <android/util/protobuf.h>
#include <stdlib.h>
@@ -52,19 +53,21 @@ EncodedBuffer::Pointer::offset() const
return mOffset;
}
-void
+EncodedBuffer::Pointer*
EncodedBuffer::Pointer::move(size_t amt)
{
size_t newOffset = mOffset + amt;
mIndex += newOffset / mChunkSize;
mOffset = newOffset % mChunkSize;
+ return this;
}
-void
+EncodedBuffer::Pointer*
EncodedBuffer::Pointer::rewind()
{
mIndex = 0;
mOffset = 0;
+ return this;
}
EncodedBuffer::Pointer
@@ -86,6 +89,7 @@ EncodedBuffer::EncodedBuffer(size_t chunkSize)
{
mChunkSize = chunkSize == 0 ? BUFFER_SIZE : chunkSize;
mWp = Pointer(mChunkSize);
+ mEp = Pointer(mChunkSize);
}
EncodedBuffer::~EncodedBuffer()
@@ -137,28 +141,136 @@ EncodedBuffer::currentToWrite()
return mChunkSize - mWp.offset();
}
+void
+EncodedBuffer::writeRawByte(uint8_t val)
+{
+ *writeBuffer() = val;
+ mWp.move();
+}
+
size_t
-EncodedBuffer::writeRawVarint(uint32_t val)
+EncodedBuffer::writeRawVarint64(uint64_t val)
{
size_t size = 0;
while (true) {
size++;
if ((val & ~0x7F) == 0) {
- *writeBuffer() = (uint8_t) val;
- mWp.move();
+ writeRawByte((uint8_t) val);
return size;
} else {
- *writeBuffer() = (uint8_t)((val & 0x7F) | 0x80);
- mWp.move();
+ writeRawByte((uint8_t)((val & 0x7F) | 0x80));
val >>= 7;
}
}
}
size_t
+EncodedBuffer::writeRawVarint32(uint32_t val)
+{
+ uint64_t v =(uint64_t)val;
+ return writeRawVarint64(v);
+}
+
+void
+EncodedBuffer::writeRawFixed32(uint32_t val)
+{
+ writeRawByte((uint8_t) val);
+ writeRawByte((uint8_t) (val>>8));
+ writeRawByte((uint8_t) (val>>16));
+ writeRawByte((uint8_t) (val>>24));
+}
+
+void
+EncodedBuffer::writeRawFixed64(uint64_t val)
+{
+ writeRawByte((uint8_t) val);
+ writeRawByte((uint8_t) (val>>8));
+ writeRawByte((uint8_t) (val>>16));
+ writeRawByte((uint8_t) (val>>24));
+ writeRawByte((uint8_t) (val>>32));
+ writeRawByte((uint8_t) (val>>40));
+ writeRawByte((uint8_t) (val>>48));
+ writeRawByte((uint8_t) (val>>56));
+}
+
+size_t
EncodedBuffer::writeHeader(uint32_t fieldId, uint8_t wireType)
{
- return writeRawVarint((fieldId << 3) | wireType);
+ return writeRawVarint32((fieldId << FIELD_ID_SHIFT) | wireType);
+}
+
+/******************************** Edit APIs ************************************************/
+EncodedBuffer::Pointer*
+EncodedBuffer::ep()
+{
+ return &mEp;
+}
+
+uint8_t
+EncodedBuffer::readRawByte()
+{
+ uint8_t val = *at(mEp);
+ mEp.move();
+ return val;
+}
+
+uint64_t
+EncodedBuffer::readRawVarint()
+{
+ uint64_t val = 0, shift = 0;
+ size_t start = mEp.pos();
+ while (true) {
+ uint8_t byte = readRawByte();
+ val += (byte & 0x7F) << shift;
+ if ((byte & 0x80) == 0) break;
+ shift += 7;
+ }
+ return val;
+}
+
+uint32_t
+EncodedBuffer::readRawFixed32()
+{
+ uint32_t val = 0;
+ for (auto i=0; i<32; i+=8) {
+ val += (uint32_t)readRawByte() << i;
+ }
+ return val;
+}
+
+uint64_t
+EncodedBuffer::readRawFixed64()
+{
+ uint64_t val = 0;
+ for (auto i=0; i<64; i+=8) {
+ val += (uint64_t)readRawByte() << i;
+ }
+ return val;
+}
+
+void
+EncodedBuffer::editRawFixed32(size_t pos, uint32_t val)
+{
+ size_t oldPos = mEp.pos();
+ mEp.rewind()->move(pos);
+ for (auto i=0; i<32; i+=8) {
+ *at(mEp) = (uint8_t) (val >> i);
+ mEp.move();
+ }
+ mEp.rewind()->move(oldPos);
+}
+
+void
+EncodedBuffer::copy(size_t srcPos, size_t size)
+{
+ if (size == 0) return;
+ Pointer cp(mChunkSize);
+ cp.move(srcPos);
+
+ while (cp.pos() < srcPos + size) {
+ writeRawByte(*at(cp));
+ cp.move();
+ }
}
/********************************* Read APIs ************************************************/
@@ -220,10 +332,10 @@ EncodedBuffer::iterator::next()
return res;
}
-uint32_t
+uint64_t
EncodedBuffer::iterator::readRawVarint()
{
- uint32_t val = 0, shift = 0;
+ uint64_t val = 0, shift = 0;
while (true) {
uint8_t byte = next();
val += (byte & 0x7F) << shift;
diff --git a/libs/protoutil/src/ProtoOutputStream.cpp b/libs/protoutil/src/ProtoOutputStream.cpp
new file mode 100644
index 000000000000..e9ca0dcb1093
--- /dev/null
+++ b/libs/protoutil/src/ProtoOutputStream.cpp
@@ -0,0 +1,652 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "libprotoutil"
+
+#include <android/util/protobuf.h>
+#include <android/util/ProtoOutputStream.h>
+#include <cutils/log.h>
+#include <cstring>
+
+namespace android {
+namespace util {
+
+/**
+ * Position of the field type in a (long long) fieldId.
+ */
+const uint64_t FIELD_TYPE_SHIFT = 32;
+
+/**
+ * Mask for the field types stored in a fieldId. Leaves a whole
+ * byte for future expansion, even though there are currently only 17 types.
+ */
+const uint64_t FIELD_TYPE_MASK = 0x0ffULL << FIELD_TYPE_SHIFT;
+
+const uint64_t FIELD_TYPE_UNKNOWN = 0;
+const uint64_t TYPE_DOUBLE = 1ULL << FIELD_TYPE_SHIFT; // double, exactly eight bytes on the wire.
+const uint64_t TYPE_FLOAT = 2ULL << FIELD_TYPE_SHIFT; // float, exactly four bytes on the wire.
+const uint64_t TYPE_INT64 = 3ULL << FIELD_TYPE_SHIFT; // int64, varint on the wire. Negative numbers
+ // take 10 bytes. Use TYPE_SINT64 if negative
+ // values are likely.
+const uint64_t TYPE_UINT64 = 4ULL << FIELD_TYPE_SHIFT; // uint64, varint on the wire.
+const uint64_t TYPE_INT32 = 5ULL << FIELD_TYPE_SHIFT; // int32, varint on the wire. Negative numbers
+ // take 10 bytes. Use TYPE_SINT32 if negative
+ // values are likely.
+const uint64_t TYPE_FIXED64 = 6ULL << FIELD_TYPE_SHIFT; // uint64, exactly eight bytes on the wire.
+const uint64_t TYPE_FIXED32 = 7ULL << FIELD_TYPE_SHIFT; // uint32, exactly four bytes on the wire.
+const uint64_t TYPE_BOOL = 8ULL << FIELD_TYPE_SHIFT; // bool, varint on the wire.
+const uint64_t TYPE_STRING = 9ULL << FIELD_TYPE_SHIFT; // UTF-8 text.
+const uint64_t TYPE_GROUP = 10ULL << FIELD_TYPE_SHIFT; // Tag-delimited message. Deprecated.
+const uint64_t TYPE_MESSAGE = 11ULL << FIELD_TYPE_SHIFT; // Length-delimited message.
+
+const uint64_t TYPE_BYTES = 12ULL << FIELD_TYPE_SHIFT; // Arbitrary byte array.
+const uint64_t TYPE_UINT32 = 13ULL << FIELD_TYPE_SHIFT; // uint32, varint on the wire
+const uint64_t TYPE_ENUM = 14ULL << FIELD_TYPE_SHIFT; // Enum, varint on the wire
+const uint64_t TYPE_SFIXED32 = 15ULL << FIELD_TYPE_SHIFT; // int32, exactly four bytes on the wire
+const uint64_t TYPE_SFIXED64 = 16ULL << FIELD_TYPE_SHIFT; // int64, exactly eight bytes on the wire
+const uint64_t TYPE_SINT32 = 17ULL << FIELD_TYPE_SHIFT; // int32, ZigZag-encoded varint on the wire
+const uint64_t TYPE_SINT64 = 18ULL << FIELD_TYPE_SHIFT; // int64, ZigZag-encoded varint on the wire
+
+//
+// FieldId flags for whether the field is single, repeated or packed.
+// TODO: packed is not supported yet.
+//
+const uint64_t FIELD_COUNT_SHIFT = 40;
+const uint64_t FIELD_COUNT_MASK = 0x0fULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_UNKNOWN = 0;
+const uint64_t FIELD_COUNT_SINGLE = 1ULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_REPEATED = 2ULL << FIELD_COUNT_SHIFT;
+const uint64_t FIELD_COUNT_PACKED = 4ULL << FIELD_COUNT_SHIFT;
+
+ProtoOutputStream::ProtoOutputStream(int fd)
+ :mBuffer(),
+ mFd(fd),
+ mCopyBegin(0),
+ mCompact(false),
+ mDepth(0),
+ mObjectId(0),
+ mExpectedObjectToken(0LL)
+{
+}
+
+ProtoOutputStream::~ProtoOutputStream()
+{
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, double val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
+ case TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
+ case TYPE_INT64: writeInt64Impl(id, (long long)val); break;
+ case TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
+ case TYPE_INT32: writeInt32Impl(id, (int)val); break;
+ case TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
+ case TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
+ case TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
+ case TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
+ case TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
+ case TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
+ case TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
+ default:
+ ALOGW("Field type %d is not supported when writing double val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, float val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
+ case TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
+ case TYPE_INT64: writeInt64Impl(id, (long long)val); break;
+ case TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
+ case TYPE_INT32: writeInt32Impl(id, (int)val); break;
+ case TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
+ case TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
+ case TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
+ case TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
+ case TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
+ case TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
+ case TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
+ default:
+ ALOGW("Field type %d is not supported when writing float val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, int val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
+ case TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
+ case TYPE_INT64: writeInt64Impl(id, (long long)val); break;
+ case TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
+ case TYPE_INT32: writeInt32Impl(id, (int)val); break;
+ case TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
+ case TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
+ case TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
+ case TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
+ case TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
+ case TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
+ case TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
+ case TYPE_ENUM: writeEnumImpl(id, (int)val); break;
+ case TYPE_BOOL: writeBoolImpl(id, val != 0); break;
+ default:
+ ALOGW("Field type %d is not supported when writing int val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, long long val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_DOUBLE: writeDoubleImpl(id, (double)val); break;
+ case TYPE_FLOAT: writeFloatImpl(id, (float)val); break;
+ case TYPE_INT64: writeInt64Impl(id, (long long)val); break;
+ case TYPE_UINT64: writeUint64Impl(id, (uint64_t)val); break;
+ case TYPE_INT32: writeInt32Impl(id, (int)val); break;
+ case TYPE_FIXED64: writeFixed64Impl(id, (uint64_t)val); break;
+ case TYPE_FIXED32: writeFixed32Impl(id, (uint32_t)val); break;
+ case TYPE_UINT32: writeUint32Impl(id, (uint32_t)val); break;
+ case TYPE_SFIXED32: writeSFixed32Impl(id, (int)val); break;
+ case TYPE_SFIXED64: writeSFixed64Impl(id, (long long)val); break;
+ case TYPE_SINT32: writeZigzagInt32Impl(id, (int)val); break;
+ case TYPE_SINT64: writeZigzagInt64Impl(id, (long long)val); break;
+ case TYPE_ENUM: writeEnumImpl(id, (int)val); break;
+ case TYPE_BOOL: writeBoolImpl(id, val != 0); break;
+ default:
+ ALOGW("Field type %d is not supported when writing long long val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, bool val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_BOOL:
+ writeBoolImpl(id, val);
+ return true;
+ default:
+ ALOGW("Field type %d is not supported when writing bool val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, string val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_STRING:
+ writeUtf8StringImpl(id, val.c_str(), val.size());
+ return true;
+ default:
+ ALOGW("Field type %d is not supported when writing string val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+}
+
+bool
+ProtoOutputStream::write(uint64_t fieldId, const char* val)
+{
+ if (mCompact) return false;
+ const uint32_t id = (uint32_t)fieldId;
+ int size = 0;
+ while (val[size] != '\0') size++;
+ switch (fieldId & FIELD_TYPE_MASK) {
+ case TYPE_STRING:
+ writeUtf8StringImpl(id, val, size);
+ return true;
+ default:
+ ALOGW("Field type %d is not supported when writing char[] val.",
+ (int)((fieldId & FIELD_TYPE_MASK) >> FIELD_TYPE_SHIFT));
+ return false;
+ }
+}
+
+/**
+ * Make a token.
+ * Bits 61-63 - tag size (So we can go backwards later if the object had not data)
+ * - 3 bits, max value 7, max value needed 5
+ * Bit 60 - true if the object is repeated
+ * Bits 59-51 - depth (For error checking)
+ * - 9 bits, max value 512, when checking, value is masked (if we really
+ * are more than 512 levels deep)
+ * Bits 32-50 - objectId (For error checking)
+ * - 19 bits, max value 524,288. that's a lot of objects. IDs will wrap
+ * because of the overflow, and only the tokens are compared.
+ * Bits 0-31 - offset of the first size field in the buffer.
+ */
+long long
+makeToken(int tagSize, bool repeated, int depth, int objectId, int sizePos) {
+ return ((0x07L & (long long)tagSize) << 61)
+ | (repeated ? (1LL << 60) : 0)
+ | (0x01ffL & (long long)depth) << 51
+ | (0x07ffffL & (long long)objectId) << 32
+ | (0x0ffffffffL & (long long)sizePos);
+}
+
+/**
+ * Get the encoded tag size from the token.
+ */
+static int getTagSizeFromToken(long long token) {
+ return (int)(0x7 & (token >> 61));
+}
+
+/**
+ * Get the nesting depth of startObject calls from the token.
+ */
+static int getDepthFromToken(long long token) {
+ return (int)(0x01ff & (token >> 51));
+}
+
+/**
+ * Get the location of the childRawSize (the first 32 bit size field) in this object.
+ */
+static int getSizePosFromToken(long long token) {
+ return (int)token;
+}
+
+long long
+ProtoOutputStream::start(uint64_t fieldId)
+{
+ if ((fieldId & FIELD_TYPE_MASK) != TYPE_MESSAGE) {
+ ALOGE("Can't call start for non-message type field: 0x%llx", (long long)fieldId);
+ return 0;
+ }
+
+ uint32_t id = (uint32_t)fieldId;
+ mBuffer.writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
+
+ size_t sizePos = mBuffer.wp()->pos();
+
+ mDepth++;
+ mObjectId++;
+ mBuffer.writeRawFixed64(mExpectedObjectToken); // push previous token into stack.
+
+ mExpectedObjectToken = makeToken(get_varint_size(id),
+ (bool)(fieldId & FIELD_COUNT_REPEATED), mDepth, mObjectId, sizePos);
+ return mExpectedObjectToken;
+}
+
+void
+ProtoOutputStream::end(long long token)
+{
+ if (token != mExpectedObjectToken) {
+ ALOGE("Unexpected token: 0x%llx, should be 0x%llx", token, mExpectedObjectToken);
+ return;
+ }
+
+ int depth = getDepthFromToken(token);
+ if (depth != (mDepth & 0x01ff)) {
+ ALOGE("Unexpected depth: %d, should be %d", depth, mDepth);
+ return;
+ }
+ mDepth--;
+
+ int sizePos = getSizePosFromToken(token);
+ // number of bytes written in this start-end session.
+ int childRawSize = mBuffer.wp()->pos() - sizePos - 8;
+
+ // retrieve the old token from stack.
+ mBuffer.ep()->rewind()->move(sizePos);
+ mExpectedObjectToken = mBuffer.readRawFixed64();
+
+ // If raw size is larger than 0, write the negative value here to indicate a compact is needed.
+ if (childRawSize > 0) {
+ mBuffer.editRawFixed32(sizePos, -childRawSize);
+ mBuffer.editRawFixed32(sizePos+4, -1);
+ } else {
+ // reset wp which erase the header tag of the message when its size is 0.
+ mBuffer.wp()->rewind()->move(sizePos - getTagSizeFromToken(token));
+ }
+}
+
+bool
+ProtoOutputStream::compact() {
+ if (mCompact) return true;
+ if (mDepth != 0) {
+ ALOGE("Can't compact when depth(%d) is not zero. Missing calls to end.", mDepth);
+ return false;
+ }
+ // record the size of the original buffer.
+ size_t rawBufferSize = mBuffer.size();
+ if (rawBufferSize == 0) return true; // nothing to do if the buffer is empty;
+
+ // reset edit pointer and recursively compute encoded size of messages.
+ mBuffer.ep()->rewind();
+ if (editEncodedSize(rawBufferSize) == 0) {
+ ALOGE("Failed to editEncodedSize.");
+ return false;
+ }
+
+ // reset both edit pointer and write pointer, and compact recursively.
+ mBuffer.ep()->rewind();
+ mBuffer.wp()->rewind();
+ if (!compactSize(rawBufferSize)) {
+ ALOGE("Failed to compactSize.");
+ return false;
+ }
+ // copy the reset to the buffer.
+ if (mCopyBegin < rawBufferSize) {
+ mBuffer.copy(mCopyBegin, rawBufferSize - mCopyBegin);
+ }
+
+ // mark true means it is not legal to write to this ProtoOutputStream anymore
+ mCompact = true;
+ return true;
+}
+
+/**
+ * First compaction pass. Iterate through the data, and fill in the
+ * nested object sizes so the next pass can compact them.
+ */
+size_t
+ProtoOutputStream::editEncodedSize(size_t rawSize)
+{
+ size_t objectStart = mBuffer.ep()->pos();
+ size_t objectEnd = objectStart + rawSize;
+ size_t encodedSize = 0;
+ int childRawSize, childEncodedSize;
+ size_t childEncodedSizePos;
+
+ while (mBuffer.ep()->pos() < objectEnd) {
+ uint32_t tag = (uint32_t)mBuffer.readRawVarint();
+ encodedSize += get_varint_size(tag);
+ switch (read_wire_type(tag)) {
+ case WIRE_TYPE_VARINT:
+ do {
+ encodedSize++;
+ } while ((mBuffer.readRawByte() & 0x80) != 0);
+ break;
+ case WIRE_TYPE_FIXED64:
+ encodedSize += 8;
+ mBuffer.ep()->move(8);
+ break;
+ case WIRE_TYPE_LENGTH_DELIMITED:
+ childRawSize = (int)mBuffer.readRawFixed32();
+ childEncodedSizePos = mBuffer.ep()->pos();
+ childEncodedSize = (int)mBuffer.readRawFixed32();
+ if (childRawSize >= 0 && childRawSize == childEncodedSize) {
+ mBuffer.ep()->move(childRawSize);
+ } else if (childRawSize < 0 && childEncodedSize == -1){
+ childEncodedSize = editEncodedSize(-childRawSize);
+ mBuffer.editRawFixed32(childEncodedSizePos, childEncodedSize);
+ } else {
+ ALOGE("Bad raw or encoded values: raw=%d, encoded=%d at %zu",
+ childRawSize, childEncodedSize, childEncodedSizePos);
+ return 0;
+ }
+ encodedSize += get_varint_size(childEncodedSize) + childEncodedSize;
+ break;
+ case WIRE_TYPE_FIXED32:
+ encodedSize += 4;
+ mBuffer.ep()->move(4);
+ break;
+ default:
+ ALOGE("Unexpected wire type %d in editEncodedSize at [%zu, %zu]",
+ read_wire_type(tag), objectStart, objectEnd);
+ return 0;
+ }
+ }
+ return encodedSize;
+}
+
+/**
+ * Second compaction pass. Iterate through the data, and copy the data
+ * forward in the buffer, converting the pairs of uint32s into a single
+ * unsigned varint of the size.
+ */
+bool
+ProtoOutputStream::compactSize(size_t rawSize)
+{
+ size_t objectStart = mBuffer.ep()->pos();
+ size_t objectEnd = objectStart + rawSize;
+ int childRawSize, childEncodedSize;
+
+ while (mBuffer.ep()->pos() < objectEnd) {
+ uint32_t tag = (uint32_t)mBuffer.readRawVarint();
+ switch (read_wire_type(tag)) {
+ case WIRE_TYPE_VARINT:
+ while ((mBuffer.readRawByte() & 0x80) != 0) {}
+ break;
+ case WIRE_TYPE_FIXED64:
+ mBuffer.ep()->move(8);
+ break;
+ case WIRE_TYPE_LENGTH_DELIMITED:
+ mBuffer.copy(mCopyBegin, mBuffer.ep()->pos() - mCopyBegin);
+
+ childRawSize = (int)mBuffer.readRawFixed32();
+ childEncodedSize = (int)mBuffer.readRawFixed32();
+ mCopyBegin = mBuffer.ep()->pos();
+
+ // write encoded size to buffer.
+ mBuffer.writeRawVarint32(childEncodedSize);
+ if (childRawSize >= 0 && childRawSize == childEncodedSize) {
+ mBuffer.ep()->move(childEncodedSize);
+ } else if (childRawSize < 0){
+ if (!compactSize(-childRawSize)) return false;
+ } else {
+ ALOGE("Bad raw or encoded values: raw=%d, encoded=%d",
+ childRawSize, childEncodedSize);
+ return false;
+ }
+ break;
+ case WIRE_TYPE_FIXED32:
+ mBuffer.ep()->move(4);
+ break;
+ default:
+ ALOGE("Unexpected wire type %d in compactSize at [%zu, %zu]",
+ read_wire_type(tag), objectStart, objectEnd);
+ return false;
+ }
+ }
+ return true;
+}
+
+static bool write_all(int fd, uint8_t const* buf, size_t size)
+{
+ while (size > 0) {
+ ssize_t amt = ::write(fd, buf, size);
+ if (amt < 0) {
+ return false;
+ }
+ size -= amt;
+ buf += amt;
+ }
+ return true;
+}
+
+bool
+ProtoOutputStream::flush()
+{
+ if (mFd < 0) return false;
+ if (!compact()) return false;
+
+ EncodedBuffer::iterator it = mBuffer.begin();
+ while (it.readBuffer() != NULL) {
+ if (!write_all(mFd, it.readBuffer(), it.currentToRead())) return false;
+ it.rp()->move(it.currentToRead());
+ }
+ return true;
+}
+
+
+// =========================================================================
+// Private functions
+
+/**
+ * bit_cast
+ */
+template <class From, class To>
+inline To bit_cast(From const &from) {
+ To to;
+ memcpy(&to, &from, sizeof(to));
+ return to;
+}
+
+inline void
+ProtoOutputStream::writeDoubleImpl(uint32_t id, double val)
+{
+ if (val == 0.0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED64);
+ mBuffer.writeRawFixed64(bit_cast<double, uint64_t>(val));
+}
+
+inline void
+ProtoOutputStream::writeFloatImpl(uint32_t id, float val)
+{
+ if (val == 0.0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED32);
+ mBuffer.writeRawFixed32(bit_cast<float, uint32_t>(val));
+}
+
+inline void
+ProtoOutputStream::writeInt64Impl(uint32_t id, long long val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint64((uint64_t)val);
+}
+
+inline void
+ProtoOutputStream::writeInt32Impl(uint32_t id, int val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32((uint32_t)val);
+}
+
+inline void
+ProtoOutputStream::writeUint64Impl(uint32_t id, uint64_t val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint64(val);
+}
+
+inline void
+ProtoOutputStream::writeUint32Impl(uint32_t id, uint32_t val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32(val);
+}
+
+inline void
+ProtoOutputStream::writeFixed64Impl(uint32_t id, uint64_t val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED64);
+ mBuffer.writeRawFixed64(val);
+}
+
+inline void
+ProtoOutputStream::writeFixed32Impl(uint32_t id, uint32_t val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED32);
+ mBuffer.writeRawFixed32(val);
+}
+
+inline void
+ProtoOutputStream::writeSFixed64Impl(uint32_t id, long long val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED64);
+ mBuffer.writeRawFixed64((uint64_t)val);
+}
+
+inline void
+ProtoOutputStream::writeSFixed32Impl(uint32_t id, int val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_FIXED32);
+ mBuffer.writeRawFixed32((uint32_t)val);
+}
+
+inline void
+ProtoOutputStream::writeZigzagInt64Impl(uint32_t id, long long val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint64((val << 1) ^ (val >> 63));
+}
+
+inline void
+ProtoOutputStream::writeZigzagInt32Impl(uint32_t id, int val)
+{
+ if (val == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32((val << 1) ^ (val >> 31));
+}
+
+inline void
+ProtoOutputStream::writeEnumImpl(uint32_t id, int val)
+{
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32((uint32_t) val);
+}
+
+inline void
+ProtoOutputStream::writeBoolImpl(uint32_t id, bool val)
+{
+ if (!val) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_VARINT);
+ mBuffer.writeRawVarint32(val ? 1 : 0);
+}
+
+inline void
+ProtoOutputStream::writeUtf8StringImpl(uint32_t id, const char* val, size_t size)
+{
+ if (val == NULL || size == 0) return;
+ mBuffer.writeHeader(id, WIRE_TYPE_LENGTH_DELIMITED);
+ mBuffer.writeRawFixed32(size);
+ mBuffer.writeRawFixed32(size);
+ for (size_t i=0; i<size; i++) {
+ mBuffer.writeRawByte((uint8_t)val[i]);
+ }
+}
+
+} // util
+} // android
+
diff --git a/libs/protoutil/src/protobuf.cpp b/libs/protoutil/src/protobuf.cpp
index ec5325c57bd1..1c7eef922895 100644
--- a/libs/protoutil/src/protobuf.cpp
+++ b/libs/protoutil/src/protobuf.cpp
@@ -22,17 +22,28 @@ namespace util {
uint8_t
read_wire_type(uint32_t varint)
{
- return (uint8_t) (varint & 0x07);
+ return (uint8_t) (varint & WIRE_TYPE_MASK);
}
uint32_t
read_field_id(uint32_t varint)
{
- return varint >> 3;
+ return varint >> FIELD_ID_SHIFT;
+}
+
+size_t
+get_varint_size(uint64_t varint)
+{
+ size_t size = 1;
+ while ((varint & ~0x7F)) {
+ size++;
+ varint >>= 7;
+ }
+ return size;
}
uint8_t*
-write_raw_varint(uint8_t* buf, uint32_t val)
+write_raw_varint(uint8_t* buf, uint64_t val)
{
uint8_t* p = buf;
while (true) {
@@ -49,7 +60,7 @@ write_raw_varint(uint8_t* buf, uint32_t val)
uint8_t*
write_length_delimited_tag_header(uint8_t* buf, uint32_t fieldId, size_t size)
{
- buf = write_raw_varint(buf, (fieldId << 3) | 2);
+ buf = write_raw_varint(buf, (fieldId << FIELD_ID_SHIFT) | WIRE_TYPE_LENGTH_DELIMITED);
buf = write_raw_varint(buf, size);
return buf;
}
diff --git a/media/java/android/media/tv/ITvInputHardware.aidl b/media/java/android/media/tv/ITvInputHardware.aidl
index 96223ba7bac1..94c1013a837e 100644
--- a/media/java/android/media/tv/ITvInputHardware.aidl
+++ b/media/java/android/media/tv/ITvInputHardware.aidl
@@ -40,12 +40,6 @@ interface ITvInputHardware {
void setStreamVolume(float volume);
/**
- * Dispatch key event to HDMI service. The events would be automatically converted to
- * HDMI CEC commands. If the hardware is not representing an HDMI port, this method will fail.
- */
- boolean dispatchKeyEventToHdmi(in KeyEvent event);
-
- /**
* Override default audio sink from audio policy. When override is on, it is
* TvInputService's responsibility to adjust to audio configuration change
* (for example, when the audio sink becomes unavailable or more desirable
diff --git a/media/java/android/media/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index d7a9edefa3f2..fd1f2cf66b79 100644
--- a/media/java/android/media/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -2590,12 +2590,9 @@ public final class TvInputManager {
}
}
+ /** @removed */
public boolean dispatchKeyEventToHdmi(KeyEvent event) {
- try {
- return mInterface.dispatchKeyEventToHdmi(event);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
+ return false;
}
public void overrideAudioSink(int audioType, String audioAddress, int samplingRate,
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index 7f6980de576a..28827e64cf96 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -24,7 +24,7 @@
#include <media/IMediaHTTPService.h>
#include <media/MediaPlayerInterface.h>
#include <media/MediaAnalyticsItem.h>
-#include <media/stagefright/Utils.h> // for FOURCC definition
+#include <media/stagefright/foundation/ByteUtils.h> // for FOURCC definition
#include <stdio.h>
#include <assert.h>
#include <limits.h>
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index db7817ec4955..5d871b3c7baf 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2270,7 +2270,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
// http://developer.android.com/guide/practices/screens_support.html#range
- mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
+ // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
+ // so if the orientation is forced, we need to respect that no matter what.
+ boolean isCar = mContext.getPackageManager().hasSystemFeature(
+ PackageManager.FEATURE_AUTOMOTIVE);
+ mForceDefaultOrientation = ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar) &&
res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation) &&
// For debug purposes the next line turns this feature off with:
// $ adb shell setprop config.override_forced_orient true
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index 6117da7b1a38..c1607e94dd1e 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -1022,20 +1022,6 @@ class TvInputHardwareManager implements TvInputHal.Callback {
}
}
- @Override
- public boolean dispatchKeyEventToHdmi(KeyEvent event) throws RemoteException {
- synchronized (mImplLock) {
- if (mReleased) {
- throw new IllegalStateException("Device already released.");
- }
- }
- if (mInfo.getType() != TvInputHardwareInfo.TV_INPUT_TYPE_HDMI) {
- return false;
- }
- // TODO(hdmi): mHdmiClient.sendKeyEvent(event);
- return false;
- }
-
private boolean startCapture(Surface surface, TvStreamConfig config) {
synchronized (mImplLock) {
if (mReleased) {