Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68cdf199 authored by Badhri Jagan Sridharan's avatar Badhri Jagan Sridharan
Browse files

Add low power stats to batteryhistory

Exports SOC specific low power state info to batterystats service.
BatteryStats service queries the powerHAL module whenever and
updates the HistoryStepDetails whenever setBatteryState is called by the
BatteryService. The stats get appended to the battery history whenever
there is a change in the battery level.

Bug: 26564574
Change-Id: I02b4db00aec0c69d1558492224f3a4dc1c386fa6
parent e4860f02
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1070,6 +1070,9 @@ public abstract class BatteryStats implements Parcelable {
        public int statSoftIrqTime;
        public int statIdlTime;

        // Platform-level low power state stats
        public String statPlatformIdleState;

        public HistoryStepDetails() {
            clear();
        }
@@ -1099,6 +1102,7 @@ public abstract class BatteryStats implements Parcelable {
            out.writeInt(statIrqTime);
            out.writeInt(statSoftIrqTime);
            out.writeInt(statIdlTime);
            out.writeString(statPlatformIdleState);
        }

        public void readFromParcel(Parcel in) {
@@ -1119,6 +1123,7 @@ public abstract class BatteryStats implements Parcelable {
            statIrqTime = in.readInt();
            statSoftIrqTime = in.readInt();
            statIdlTime = in.readInt();
            statPlatformIdleState = in.readString();
        }
    }

@@ -4788,6 +4793,8 @@ public abstract class BatteryStats implements Parcelable {
                            pw.print(sb);
                            pw.print(")");
                        }
                        pw.print(", PlatformIdleStat ");
                        pw.print(rec.stepDetails.statPlatformIdleState);
                        pw.println();
                    } else {
                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
@@ -4821,6 +4828,8 @@ public abstract class BatteryStats implements Parcelable {
                        pw.print(rec.stepDetails.statSoftIrqTime);
                        pw.print(',');
                        pw.print(rec.stepDetails.statIdlTime);
                        pw.print(',');
                        pw.print(rec.stepDetails.statPlatformIdleState);
                        pw.println();
                    }
                }
+24 −3
Original line number Diff line number Diff line
@@ -108,7 +108,7 @@ public class BatteryStatsImpl extends BatteryStats {
    private static final int MAGIC = 0xBA757475; // 'BATSTATS'

    // Current on-disk Parcel version
    private static final int VERSION = 142 + (USE_OLD_HISTORY ? 1000 : 0);
    private static final int VERSION = 143 + (USE_OLD_HISTORY ? 1000 : 0);

    // Maximum number of items we will record in the history.
    private static final int MAX_HISTORY_ITEMS = 2000;
@@ -150,6 +150,13 @@ public class BatteryStatsImpl extends BatteryStats {
        public void batterySendBroadcast(Intent intent);
    }

    public interface PlatformIdleStateCallback {
        public String getPlatformLowPowerStats();
    }

    private final PlatformIdleStateCallback mPlatformIdleStateCallback;


    final class MyHandler extends Handler {
        public MyHandler(Looper looper) {
            super(looper, null, true);
@@ -569,6 +576,7 @@ public class BatteryStatsImpl extends BatteryStats {
        mDailyFile = null;
        mHandler = null;
        mExternalSync = null;
        mPlatformIdleStateCallback = null;
        clearHistoryLocked();
    }

@@ -2220,6 +2228,12 @@ public class BatteryStatsImpl extends BatteryStats {
                    + cur.eventTag.string);
        }
        if (computeStepDetails) {
            if (mPlatformIdleStateCallback != null) {
                mCurHistoryStepDetails.statPlatformIdleState =
                        mPlatformIdleStateCallback.getPlatformLowPowerStats();
                if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
                        mCurHistoryStepDetails.statPlatformIdleState);
            }
            computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
            if (includeStepDetails != 0) {
                mCurHistoryStepDetails.writeToParcel(dest);
@@ -7372,11 +7386,16 @@ public class BatteryStatsImpl extends BatteryStats {
    }

    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync) {
        this(new SystemClocks(), systemDir, handler, externalSync);
        this(new SystemClocks(), systemDir, handler, externalSync, null);
    }

    public BatteryStatsImpl(File systemDir, Handler handler, ExternalStatsSync externalSync,
                            PlatformIdleStateCallback cb) {
        this(new SystemClocks(), systemDir, handler, externalSync, cb);
    }

    public BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler,
            ExternalStatsSync externalSync) {
            ExternalStatsSync externalSync, PlatformIdleStateCallback cb) {
        init(clocks);

        if (systemDir != null) {
@@ -7462,6 +7481,7 @@ public class BatteryStatsImpl extends BatteryStats {
        initDischarge();
        clearHistoryLocked();
        updateDailyDeadlineLocked();
        mPlatformIdleStateCallback = cb;
    }

    public BatteryStatsImpl(Parcel p) {
@@ -7477,6 +7497,7 @@ public class BatteryStatsImpl extends BatteryStats {
        mExternalSync = null;
        clearHistoryLocked();
        readFromParcel(p);
        mPlatformIdleStateCallback = null;
    }

    public void setPowerProfile(PowerProfile profile) {
+31 −3
Original line number Diff line number Diff line
@@ -79,7 +79,8 @@ import java.util.concurrent.TimeoutException;
 * battery life.
 */
public final class BatteryStatsService extends IBatteryStats.Stub
        implements PowerManagerInternal.LowPowerModeListener {
        implements PowerManagerInternal.LowPowerModeListener,
        BatteryStatsImpl.PlatformIdleStateCallback {
    static final String TAG = "BatteryStatsService";

    /**
@@ -173,6 +174,33 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        }
    }

    private native int getPlatformLowPowerStats(ByteBuffer outBuffer);
    private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8
                    .newDecoder()
                    .onMalformedInput(CodingErrorAction.REPLACE)
                    .onUnmappableCharacter(CodingErrorAction.REPLACE)
                    .replaceWith("?");
    private ByteBuffer mUtf8BufferStat = ByteBuffer.allocateDirect(MAX_LOW_POWER_STATS_SIZE);
    private CharBuffer mUtf16BufferStat = CharBuffer.allocate(MAX_LOW_POWER_STATS_SIZE);
    private static final int MAX_LOW_POWER_STATS_SIZE = 512;

    @Override
    public String getPlatformLowPowerStats() {
        mUtf8BufferStat.clear();
        mUtf16BufferStat.clear();
        mDecoderStat.reset();
        int bytesWritten = getPlatformLowPowerStats(mUtf8BufferStat);
        if (bytesWritten < 0) {
            return null;
        } else if (bytesWritten == 0) {
            return "Empty";
        }
        mUtf8BufferStat.limit(bytesWritten);
        mDecoderStat.decode(mUtf8BufferStat, mUtf16BufferStat, true);
        mUtf16BufferStat.flip();
        return mUtf16BufferStat.toString();
    }

    BatteryStatsService(File systemDir, Handler handler) {
        // Our handler here will be accessing the disk, use a different thread than
        // what the ActivityManagerService gave us (no I/O on that one!).
@@ -182,7 +210,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        mHandler = new BatteryStatsHandler(thread.getLooper());

        // BatteryStatsImpl expects the ActivityManagerService handler, so pass that one through.
        mStats = new BatteryStatsImpl(systemDir, handler, mHandler);
        mStats = new BatteryStatsImpl(systemDir, handler, mHandler, this);
    }

    public void publish(Context context) {
+117 −0
Original line number Diff line number Diff line
@@ -27,8 +27,10 @@
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/power.h>
#include <suspend/autosuspend.h>

#include <inttypes.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
@@ -47,6 +49,7 @@ namespace android

static bool wakeup_init = false;
static sem_t wakeup_sem;
extern struct power_module* gPowerModule;

static void wakeup_callback(bool success)
{
@@ -170,8 +173,122 @@ static jint nativeWaitWakeup(JNIEnv *env, jobject clazz, jobject outBuf)
    return mergedreasonpos - mergedreason;
}

static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
    int num_modes = -1;
    char *output = (char*)env->GetDirectBufferAddress(outBuf), *offset = output;
    int remaining = (int)env->GetDirectBufferCapacity(outBuf);
    power_state_platform_sleep_state_t *list;
    size_t *voter_list;
    int total_added = -1;

    if (outBuf == NULL) {
        jniThrowException(env, "java/lang/NullPointerException", "null argument");
        goto error;
    }

    if (!gPowerModule) {
        ALOGE("%s: gPowerModule not loaded", POWER_HARDWARE_MODULE_ID);
        goto error;
    }

    if (! (gPowerModule->get_platform_low_power_stats && gPowerModule->get_number_of_platform_modes
       && gPowerModule->get_voter_list)) {
        ALOGE("%s: Missing API", POWER_HARDWARE_MODULE_ID);
        goto error;
    }

    if (gPowerModule->get_number_of_platform_modes) {
        num_modes = gPowerModule->get_number_of_platform_modes(gPowerModule);
    }

    if (num_modes < 1) {
        ALOGE("%s: Platform does not even have one low power mode", POWER_HARDWARE_MODULE_ID);
        goto error;
    }

    list = (power_state_platform_sleep_state_t *)calloc(num_modes,
        sizeof(power_state_platform_sleep_state_t));
    if (!list) {
        ALOGE("%s: power_state_platform_sleep_state_t allocation failed", POWER_HARDWARE_MODULE_ID);
        goto error;
    }

    voter_list = (size_t *)calloc(num_modes, sizeof(*voter_list));
    if (!voter_list) {
        ALOGE("%s: voter_list allocation failed", POWER_HARDWARE_MODULE_ID);
        goto err_free;
    }

    gPowerModule->get_voter_list(gPowerModule, voter_list);

    for (int i = 0; i < num_modes; i++) {
        list[i].voters = (power_state_voter_t *)calloc(voter_list[i],
                         sizeof(power_state_voter_t));
        if (!list[i].voters) {
            ALOGE("%s: voter_t allocation failed", POWER_HARDWARE_MODULE_ID);
            goto err_free;
        }
    }

    if (!gPowerModule->get_platform_low_power_stats(gPowerModule, list)) {
        for (int i = 0; i < num_modes; i++) {
            int added;

            added = snprintf(offset, remaining, "%s_time=%" PRIu64 " %s_count=%" PRIu64 " ",
                    list[i].name, list[i].residency_in_msec_since_boot, list[i].name,
                    list[i].total_transitions);
            if (added < 0) {
                break;
            }
            if (added > remaining) {
                added = remaining;
            }
            offset += added;
            remaining -= added;
            total_added += added;

            for (unsigned int j = 0; j < list[i].number_of_voters; j++) {
                added = snprintf(offset, remaining, "%s_time=%" PRIu64 " %s_count=%" PRIu64 " ",
                        list[i].voters[j].name,
                        list[i].voters[j].total_time_in_msec_voted_for_since_boot,
                        list[i].voters[j].name,
                        list[i].voters[j].total_number_of_times_voted_since_boot);
                if (added < 0) {
                    break;
                }
                if (added > remaining) {
                    added = remaining;
                }
                offset += added;
                remaining -= added;
                total_added += added;
            }

            if (remaining <= 0) {
                /* rewrite NULL character*/
                offset--;
                total_added--;
                ALOGE("%s module: buffer not enough", POWER_HARDWARE_MODULE_ID);
                break;
            }
        }
    }
    *offset = 0;
    total_added += 1;

err_free:
    for (int i = 0; i < num_modes; i++) {
        free(list[i].voters);
    }
    free(list);
    free(voter_list);
error:
    return total_added;
}

static const JNINativeMethod method_table[] = {
    { "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup },
    { "getPlatformLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getPlatformLowPowerStats },
};

int register_android_server_BatteryStatsService(JNIEnv *env)
+1 −1
Original line number Diff line number Diff line
@@ -48,7 +48,7 @@ static struct {
// ----------------------------------------------------------------------------

static jobject gPowerManagerServiceObj;
static struct power_module* gPowerModule;
struct power_module* gPowerModule;

static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];