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

Commit 0a4e1148 authored by Ahmed ElArabawy's avatar Ahmed ElArabawy
Browse files

power hal: Use power HAL API 1.1



Switch framework to use Power HAL 1.1

Many subsystems (e.g.wifi) could be living on an
independent power island (sourced from VBatt directly)
and might even have their own dedicated XTAL to source
their clocks. Since these SOCs are capable of
autonomously operating (while the platform is in one
of the sleep states), they are still drawing power
from the VBatt. Hence it is critical to understand
the  (SOC) level low power statistics as well when
the battery level changes and be able to find any
correlation in event of unexpected battery drain.

This commit directs framework to use Power HAL 1.1

Bug: 29339696
Test: Manual
Change-Id: I0d779365536e84de5ec50b97d50f0162738383da
Signed-off-by: default avatarAhmed ElArabawy <arabawy@google.com>
parent e6318c28
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -1157,6 +1157,7 @@ public abstract class BatteryStats implements Parcelable {

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

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

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

@@ -5296,6 +5299,10 @@ public abstract class BatteryStats implements Parcelable {
                        pw.print(", PlatformIdleStat ");
                        pw.print(rec.stepDetails.statPlatformIdleState);
                        pw.println();

                        pw.print(", SubsystemPowerState ");
                        pw.print(rec.stepDetails.statSubsystemPowerState);
                        pw.println();
                    } else {
                        pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
                        pw.print(HISTORY_DATA); pw.print(",0,Dcpu=");
@@ -5333,6 +5340,11 @@ public abstract class BatteryStats implements Parcelable {
                            pw.print(rec.stepDetails.statPlatformIdleState);
                        }
                        pw.println();

                        if (rec.stepDetails.statSubsystemPowerState != null) {
                            pw.print(rec.stepDetails.statSubsystemPowerState);
                        }
                        pw.println();
                    }
                }
                oldState = rec.states;
+7 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ public class BatteryStatsImpl extends BatteryStats {

    public interface PlatformIdleStateCallback {
        public String getPlatformLowPowerStats();
        public String getSubsystemLowPowerStats();
    }

    private final PlatformIdleStateCallback mPlatformIdleStateCallback;
@@ -2707,6 +2708,12 @@ public class BatteryStatsImpl extends BatteryStats {
                        mPlatformIdleStateCallback.getPlatformLowPowerStats();
                if (DEBUG) Slog.i(TAG, "WRITE PlatformIdleState:" +
                        mCurHistoryStepDetails.statPlatformIdleState);

                mCurHistoryStepDetails.statSubsystemPowerState =
                        mPlatformIdleStateCallback.getSubsystemLowPowerStats();
                if (DEBUG) Slog.i(TAG, "WRITE SubsystemPowerState:" +
                        mCurHistoryStepDetails.statSubsystemPowerState);

            }
            computeHistoryStepDetails(mCurHistoryStepDetails, mLastHistoryStepDetails);
            if (includeStepDetails != 0) {
+23 −0
Original line number Diff line number Diff line
@@ -183,6 +183,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
    }

    private native int getPlatformLowPowerStats(ByteBuffer outBuffer);
    private native int getSubsystemLowPowerStats(ByteBuffer outBuffer);
    private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8
                    .newDecoder()
                    .onMalformedInput(CodingErrorAction.REPLACE)
@@ -214,6 +215,28 @@ public final class BatteryStatsService extends IBatteryStats.Stub
        }
    }

    @Override
    public String getSubsystemLowPowerStats() {
        Slog.d(TAG, "begin getSubsystemLowPowerStats");
        try {
            mUtf8BufferStat.clear();
            mUtf16BufferStat.clear();
            mDecoderStat.reset();
            int bytesWritten = getSubsystemLowPowerStats(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();
        } finally {
            Slog.d(TAG, "end getSubsystemLowPowerStats");
        }
    }

    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!).
+1 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@ LOCAL_SHARED_LIBRARIES += \
    android.hardware.ir@1.0 \
    android.hardware.light@2.0 \
    android.hardware.power@1.0 \
    android.hardware.power@1.1 \
    android.hardware.thermal@1.0 \
    android.hardware.tv.cec@1.0 \
    android.hardware.tv.input@1.0 \
+99 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include <unistd.h>

#include <android/hardware/power/1.0/IPower.h>
#include <android/hardware/power/1.1/IPower.h>
#include <android_runtime/AndroidRuntime.h>
#include <jni.h>

@@ -46,6 +47,8 @@ using android::hardware::power::V1_0::IPower;
using android::hardware::power::V1_0::PowerStatePlatformSleepState;
using android::hardware::power::V1_0::PowerStateVoter;
using android::hardware::power::V1_0::Status;
using android::hardware::power::V1_1::PowerStateSubsystem;
using android::hardware::power::V1_1::PowerStateSubsystemSleepState;
using android::hardware::hidl_vec;

namespace android
@@ -263,9 +266,105 @@ static jint getPlatformLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject o
    return total_added;
}

static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject outBuf) {
    char *output = (char*)env->GetDirectBufferAddress(outBuf);
    char *offset = output;
    int remaining = (int)env->GetDirectBufferCapacity(outBuf);
    int total_added = -1;

	//This is a IPower 1.1 API
    sp<android::hardware::power::V1_1::IPower> gPowerHal_1_1 = nullptr;

    if (outBuf == NULL) {
        jniThrowException(env, "java/lang/NullPointerException", "null argument");
        return -1;
    }

    {
        std::lock_guard<std::mutex> lock(gPowerHalMutex);
        if (!getPowerHal()) {
            ALOGE("Power Hal not loaded");
            return -1;
        }

        //Trying to cast to 1.1, this will succeed only for devices supporting 1.1
        gPowerHal_1_1 = android::hardware::power::V1_1::IPower::castFrom(gPowerHal);
    	if (gPowerHal_1_1 == nullptr) {
            //This device does not support IPower@1.1, exiting gracefully
            return 0;
    	}

        Return<void> ret = gPowerHal_1_1->getSubsystemLowPowerStats(
           [&offset, &remaining, &total_added](hidl_vec<PowerStateSubsystem> subsystems,
                Status status) {

            if (status != Status::SUCCESS)
                return;

            for (size_t i = 0; i < subsystems.size(); i++) {
                int added;
                const PowerStateSubsystem &subsystem = subsystems[i];

                added = snprintf(offset, remaining,
                                 "subsystem_%zu name=%s ", i + 1, subsystem.name.c_str());
                if (added < 0) {
                    break;
                }

                if (added > remaining) {
                    added = remaining;
                }

                offset += added;
                remaining -= added;
                total_added += added;

                for (size_t j = 0; j < subsystem.states.size(); j++) {
                    const PowerStateSubsystemSleepState& state = subsystem.states[j];
                    added = snprintf(offset, remaining,
                                     "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " last entry TS(ms)=%" PRIu64 " ",
                                     j + 1, state.name.c_str(), state.residencyInMsecSinceBoot,
                                     state.totalTransitions, state.lastEntryTimestampMs);
                    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("PowerHal: buffer not enough");
                    break;
                }
            }
        }
        );

        if (!ret.isOk()) {
            ALOGE("getSubsystemLowPowerStats() failed: power HAL service not available");
            gPowerHal = nullptr;
            return -1;
        }
    }

    *offset = 0;
    total_added += 1;
    return total_added;
}

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

int register_android_server_BatteryStatsService(JNIEnv *env)