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

Commit b86d026a authored by Todd Poynor's avatar Todd Poynor Committed by Android (Google) Code Review
Browse files

Merge "BatteryService: Allow power supplies to switch type between AC and USB"

parents b20abf41 701bfb10
Loading
Loading
Loading
Loading
+142 −82
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@
#include <unistd.h>
#include <dirent.h>
#include <linux/ioctl.h>
#include <utils/Vector.h>
#include <utils/String8.h>

namespace android {

@@ -70,21 +72,28 @@ struct BatteryManagerConstants {
static BatteryManagerConstants gConstants;

struct PowerSupplyPaths {
    char* acOnlinePath;
    char* usbOnlinePath;
    char* wirelessOnlinePath;
    char* batteryStatusPath;
    char* batteryHealthPath;
    char* batteryPresentPath;
    char* batteryCapacityPath;
    char* batteryVoltagePath;
    char* batteryTemperaturePath;
    char* batteryTechnologyPath;
    String8 batteryStatusPath;
    String8 batteryHealthPath;
    String8 batteryPresentPath;
    String8 batteryCapacityPath;
    String8 batteryVoltagePath;
    String8 batteryTemperaturePath;
    String8 batteryTechnologyPath;
};
static PowerSupplyPaths gPaths;

static Vector<String8> gChargerNames;

static int gVoltageDivisor = 1;

enum PowerSupplyType {
     ANDROID_POWER_SUPPLY_TYPE_UNKNOWN = 0,
     ANDROID_POWER_SUPPLY_TYPE_AC,
     ANDROID_POWER_SUPPLY_TYPE_USB,
     ANDROID_POWER_SUPPLY_TYPE_WIRELESS,
     ANDROID_POWER_SUPPLY_TYPE_BATTERY
};

static jint getBatteryStatus(const char* status)
{
    switch (status[0]) {
@@ -133,13 +142,13 @@ static jint getBatteryHealth(const char* status)
    }
}

static int readFromFile(const char* path, char* buf, size_t size)
static int readFromFile(const String8& path, char* buf, size_t size)
{
    if (!path)
        return -1;
    int fd = open(path, O_RDONLY, 0);
    int fd = open(path.string(), O_RDONLY, 0);
    if (fd == -1) {
        ALOGE("Could not open '%s'", path);
        ALOGE("Could not open '%s'", path.string());
        return -1;
    }
    
@@ -156,7 +165,7 @@ static int readFromFile(const char* path, char* buf, size_t size)
    return count;
}

static void setBooleanField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)
static void setBooleanField(JNIEnv* env, jobject obj, const String8& path, jfieldID fieldID)
{
    const int SIZE = 16;
    char buf[SIZE];
@@ -170,7 +179,7 @@ static void setBooleanField(JNIEnv* env, jobject obj, const char* path, jfieldID
    env->SetBooleanField(obj, fieldID, value);
}

static void setIntField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)
static void setIntField(JNIEnv* env, jobject obj, const String8& path, jfieldID fieldID)
{
    const int SIZE = 128;
    char buf[SIZE];
@@ -182,7 +191,7 @@ static void setIntField(JNIEnv* env, jobject obj, const char* path, jfieldID fie
    env->SetIntField(obj, fieldID, value);
}

static void setVoltageField(JNIEnv* env, jobject obj, const char* path, jfieldID fieldID)
static void setVoltageField(JNIEnv* env, jobject obj, const String8& path, jfieldID fieldID)
{
    const int SIZE = 128;
    char buf[SIZE];
@@ -195,12 +204,29 @@ static void setVoltageField(JNIEnv* env, jobject obj, const char* path, jfieldID
    env->SetIntField(obj, fieldID, value);
}

static PowerSupplyType readPowerSupplyType(const String8& path) {
    const int SIZE = 128;
    char buf[SIZE];
    int length = readFromFile(path, buf, SIZE);

    if (length <= 0)
        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
    if (buf[length - 1] == '\n')
        buf[length - 1] = 0;
    if (strcmp(buf, "Battery") == 0)
        return ANDROID_POWER_SUPPLY_TYPE_BATTERY;
    else if (strcmp(buf, "Mains") == 0)
        return ANDROID_POWER_SUPPLY_TYPE_AC;
    else if (strcmp(buf, "USB") == 0)
        return ANDROID_POWER_SUPPLY_TYPE_USB;
    else if (strcmp(buf, "Wireless") == 0)
        return ANDROID_POWER_SUPPLY_TYPE_WIRELESS;
    else
        return ANDROID_POWER_SUPPLY_TYPE_UNKNOWN;
}

static void android_server_BatteryService_update(JNIEnv* env, jobject obj)
{
    setBooleanField(env, obj, gPaths.acOnlinePath, gFieldIds.mAcOnline);
    setBooleanField(env, obj, gPaths.usbOnlinePath, gFieldIds.mUsbOnline);
    setBooleanField(env, obj, gPaths.wirelessOnlinePath, gFieldIds.mWirelessOnline);
    setBooleanField(env, obj, gPaths.batteryPresentPath, gFieldIds.mBatteryPresent);
    
    setIntField(env, obj, gPaths.batteryCapacityPath, gFieldIds.mBatteryLevel);
@@ -221,6 +247,44 @@ static void android_server_BatteryService_update(JNIEnv* env, jobject obj)

    if (readFromFile(gPaths.batteryTechnologyPath, buf, SIZE) > 0)
        env->SetObjectField(obj, gFieldIds.mBatteryTechnology, env->NewStringUTF(buf));

    unsigned int i;
    String8 path;
    jboolean acOnline = false;
    jboolean usbOnline = false;
    jboolean wirelessOnline = false;

    for (i = 0; i < gChargerNames.size(); i++) {
        path.clear();
        path.appendFormat("%s/%s/online", POWER_SUPPLY_PATH,
                          gChargerNames[i].string());

        if (readFromFile(path, buf, SIZE) > 0) {
            if (buf[0] != '0') {
                path.clear();
                path.appendFormat("%s/%s/type", POWER_SUPPLY_PATH,
                                  gChargerNames[i].string());
                switch(readPowerSupplyType(path)) {
                case ANDROID_POWER_SUPPLY_TYPE_AC:
                    acOnline = true;
                    break;
                case ANDROID_POWER_SUPPLY_TYPE_USB:
                    usbOnline = true;
                    break;
                case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
                    wirelessOnline = true;
                    break;
                default:
                    ALOGW("%s: Unknown power supply type",
                          gChargerNames[i].string());
                }
            }
        }
    }

    env->SetBooleanField(obj, gFieldIds.mAcOnline, acOnline);
    env->SetBooleanField(obj, gFieldIds.mUsbOnline, usbOnline);
    env->SetBooleanField(obj, gFieldIds.mWirelessOnline, wirelessOnline);
}

static JNINativeMethod sMethods[] = {
@@ -230,7 +294,7 @@ static JNINativeMethod sMethods[] = {

int register_android_server_BatteryService(JNIEnv* env)
{
    char    path[PATH_MAX];
    String8 path;
    struct dirent* entry;

    DIR* dir = opendir(POWER_SUPPLY_PATH);
@@ -247,76 +311,72 @@ int register_android_server_BatteryService(JNIEnv* env)

            char buf[20];
            // Look for "type" file in each subdirectory
            snprintf(path, sizeof(path), "%s/%s/type", POWER_SUPPLY_PATH, name);
            int length = readFromFile(path, buf, sizeof(buf));
            if (length > 0) {
                if (buf[length - 1] == '\n')
                    buf[length - 1] = 0;

                if (strcmp(buf, "Mains") == 0) {
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
            path.clear();
            path.appendFormat("%s/%s/type", POWER_SUPPLY_PATH, name);
            switch(readPowerSupplyType(path)) {
            case ANDROID_POWER_SUPPLY_TYPE_AC:
            case ANDROID_POWER_SUPPLY_TYPE_USB:
            case ANDROID_POWER_SUPPLY_TYPE_WIRELESS:
                path.clear();
                path.appendFormat("%s/%s/online", POWER_SUPPLY_PATH, name);
                if (access(path.string(), R_OK) == 0)
                    gChargerNames.add(String8(name));
                break;

            case ANDROID_POWER_SUPPLY_TYPE_BATTERY:
                path.clear();
                path.appendFormat("%s/%s/status", POWER_SUPPLY_PATH, name);
                if (access(path, R_OK) == 0)
                        gPaths.acOnlinePath = strdup(path);
                }
                else if (strcmp(buf, "USB") == 0) {
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
                    if (access(path, R_OK) == 0)
                        gPaths.usbOnlinePath = strdup(path);
                }
                else if (strcmp(buf, "Wireless") == 0) {
                    snprintf(path, sizeof(path), "%s/%s/online", POWER_SUPPLY_PATH, name);
                    gPaths.batteryStatusPath = path;
                path.clear();
                path.appendFormat("%s/%s/health", POWER_SUPPLY_PATH, name);
                if (access(path, R_OK) == 0)
                        gPaths.wirelessOnlinePath = strdup(path);
                }
                else if (strcmp(buf, "Battery") == 0) {
                    snprintf(path, sizeof(path), "%s/%s/status", POWER_SUPPLY_PATH, name);
                    gPaths.batteryHealthPath = path;
                path.clear();
                path.appendFormat("%s/%s/present", POWER_SUPPLY_PATH, name);
                if (access(path, R_OK) == 0)
                        gPaths.batteryStatusPath = strdup(path);
                    snprintf(path, sizeof(path), "%s/%s/health", POWER_SUPPLY_PATH, name);
                    gPaths.batteryPresentPath = path;
                path.clear();
                path.appendFormat("%s/%s/capacity", POWER_SUPPLY_PATH, name);
                if (access(path, R_OK) == 0)
                        gPaths.batteryHealthPath = strdup(path);
                    snprintf(path, sizeof(path), "%s/%s/present", POWER_SUPPLY_PATH, name);
                    if (access(path, R_OK) == 0)
                        gPaths.batteryPresentPath = strdup(path);
                    snprintf(path, sizeof(path), "%s/%s/capacity", POWER_SUPPLY_PATH, name);
                    if (access(path, R_OK) == 0)
                        gPaths.batteryCapacityPath = strdup(path);
                    gPaths.batteryCapacityPath = path;

                    snprintf(path, sizeof(path), "%s/%s/voltage_now", POWER_SUPPLY_PATH, name);
                path.clear();
                path.appendFormat("%s/%s/voltage_now", POWER_SUPPLY_PATH, name);
                if (access(path, R_OK) == 0) {
                        gPaths.batteryVoltagePath = strdup(path);
                    gPaths.batteryVoltagePath = path;
                    // voltage_now is in microvolts, not millivolts
                    gVoltageDivisor = 1000;
                } else {
                        snprintf(path, sizeof(path), "%s/%s/batt_vol", POWER_SUPPLY_PATH, name);
                    path.clear();
                    path.appendFormat("%s/%s/batt_vol", POWER_SUPPLY_PATH, name);
                    if (access(path, R_OK) == 0)
                            gPaths.batteryVoltagePath = strdup(path);
                            gPaths.batteryVoltagePath = path;
                }

                    snprintf(path, sizeof(path), "%s/%s/temp", POWER_SUPPLY_PATH, name);
                path.clear();
                path.appendFormat("%s/%s/temp", POWER_SUPPLY_PATH, name);
                if (access(path, R_OK) == 0) {
                        gPaths.batteryTemperaturePath = strdup(path);
                    gPaths.batteryTemperaturePath = path;
                } else {
                        snprintf(path, sizeof(path), "%s/%s/batt_temp", POWER_SUPPLY_PATH, name);
                    path.clear();
                    path.appendFormat("%s/%s/batt_temp", POWER_SUPPLY_PATH, name);
                    if (access(path, R_OK) == 0)
                            gPaths.batteryTemperaturePath = strdup(path);
                            gPaths.batteryTemperaturePath = path;
                }

                    snprintf(path, sizeof(path), "%s/%s/technology", POWER_SUPPLY_PATH, name);
                path.clear();
                path.appendFormat("%s/%s/technology", POWER_SUPPLY_PATH, name);
                if (access(path, R_OK) == 0)
                        gPaths.batteryTechnologyPath = strdup(path);
                }
                    gPaths.batteryTechnologyPath = path;
                break;
            }
        }
        closedir(dir);
    }

    if (!gPaths.acOnlinePath)
        ALOGE("acOnlinePath not found");
    if (!gPaths.usbOnlinePath)
        ALOGE("usbOnlinePath not found");
    if (!gPaths.wirelessOnlinePath)
        ALOGE("wirelessOnlinePath not found");
    if (!gChargerNames.size())
        ALOGE("No charger supplies found");
    if (!gPaths.batteryStatusPath)
        ALOGE("batteryStatusPath not found");
    if (!gPaths.batteryHealthPath)