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

Commit d4cca214 authored by Vachounet's avatar Vachounet Committed by Nolen Johnson
Browse files

BatteryService: Add support for battery Moto Mods

* This relies on the prebuilt Moto Health service being
  included device side.

Reference: I48803eeb72499fe8459805f6ef80ef5f868f431e
Change-Id: I41a4d5fdeb5e1f2ad7838851ad0815cef7d72980
parent 3e9fa164
Loading
Loading
Loading
Loading
+50 −1
Original line number Diff line number Diff line
@@ -164,6 +164,54 @@ public class BatteryManager {
    @SystemApi
    public static final String EXTRA_EVENT_TIMESTAMP = "android.os.extra.EVENT_TIMESTAMP";

    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * Contains a value that forces Moto Mod battery level `mod_level`
     * to overwrite the interal battery level and act as the device's
     * sole battery. This isn't used by any Mods we have come across.
     * {@hide}
     */
    public static final String EXTRA_MOD_FLAG = "mod_flag";

    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * Contains battery percentage value for Moto Mod devices.
     * {@hide}
     */
    public static final String EXTRA_MOD_LEVEL = "mod_level";

    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * Contains Moto Mod power source type value.
     * {@hide}
     */
    public static final String EXTRA_MOD_POWER_SOURCE = "mod_psrc";

    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * Contains Moto Mod status (ready, charging, etc.) value.
     * {@hide}
     */
    public static final String EXTRA_MOD_STATUS = "mod_status";

    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * Contains Moto Mod type information (battery, audio, input).
     * {@hide}
     */
    public static final String EXTRA_MOD_TYPE = "mod_type";

    /**
     * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
     * Contains Moto Mod connection indicator.
     * {@hide}
     */
    public static final String EXTRA_PLUGGED_RAW = "plugged_raw";

    public static final int BATTERY_PROPERTY_MOD_CHARGE_FULL = 100;
    public static final int BATTERY_PROPERTY_CHARGE_FULL = 101;
    public static final int BATTERY_PLUGGED_MOD = 8;

    // values for "status" field in the ACTION_BATTERY_CHANGED Intent
    public static final int BATTERY_STATUS_UNKNOWN = Constants.BATTERY_STATUS_UNKNOWN;
    public static final int BATTERY_STATUS_CHARGING = Constants.BATTERY_STATUS_CHARGING;
@@ -191,7 +239,8 @@ public class BatteryManager {

    /** @hide */
    public static final int BATTERY_PLUGGED_ANY =
            BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
            BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS |
            BATTERY_PLUGGED_MOD;

    /**
     * Sent when the device's battery has started charging (or has reached full charge
+1 −0
Original line number Diff line number Diff line
@@ -129,6 +129,7 @@ java_library_static {
        "android.hidl.manager-V1.2-java",
        "capture_state_listener-aidl-java",
        "dnsresolver_aidl_interface-java",
        "motorola.hardware.health-V1.0-java",
        "netd_aidl_interfaces-platform-java",
        "org.lineageos.platform.internal",
        "overlayable_policy_aidl-java",
+96 −3
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.ShellCommand;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
import android.os.UEventObserver;
import android.os.UserHandle;
@@ -75,9 +76,11 @@ import com.android.server.lights.LogicalLight;
import org.lineageos.internal.notification.LedValues;
import org.lineageos.internal.notification.LineageBatteryLights;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayDeque;
@@ -88,6 +91,9 @@ import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;

import motorola.hardware.health.V1_0.BatteryProperties;
import motorola.hardware.health.V1_0.IMotHealth;

/**
 * <p>BatteryService monitors the charging status, and charge level of the device
 * battery.  When these values change this service broadcasts the new values
@@ -201,6 +207,16 @@ public final class BatteryService extends SystemService {

    private LineageBatteryLights mLineageBatteryLights;

    private static final int MOD_TYPE_EMERGENCY = 3;
    private static final int MOD_TYPE_SUPPLEMENTAL = 2;
    private BatteryProperties mBatteryModProps;
    private IMotHealth mMotHealthService = null;
    private int mLastModFlag;
    private int mLastModLevel;
    private int mLastModPowerSource;
    private int mLastModStatus;
    private int mLastModType;

    public BatteryService(Context context) {
        super(context);

@@ -238,6 +254,20 @@ public final class BatteryService extends SystemService {
            invalidChargerObserver.startObserving(
                    "DEVPATH=/devices/virtual/switch/invalid_charger");
        }

        mBatteryModProps = new BatteryProperties();
        mBatteryModProps.modLevel = -1;
        mBatteryModProps.modStatus = 1;
        mBatteryModProps.modFlag = 0;
        mBatteryModProps.modType = 0;
        mBatteryModProps.modPowerSource = 0;
        try {
            mMotHealthService = IMotHealth.getService();
        } catch (RemoteException e) {
            Slog.e(TAG, "health: cannot get service. (RemoteException)");
        } catch (NoSuchElementException e2) {
            Slog.e(TAG, "mothealth: cannot get service. (no supported health HAL service)");
        }
    }

    @Override
@@ -357,6 +387,10 @@ public final class BatteryService extends SystemService {
        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_WIRELESS) != 0 && mHealthInfo.chargerWirelessOnline) {
            return true;
        }
        if ((plugTypeSet & BatteryManager.BATTERY_PLUGGED_MOD) != 0 ||
            mPlugType == BatteryManager.BATTERY_PLUGGED_MOD || isModBatteryActive()) {
            return true;
        }
        return false;
    }

@@ -449,6 +483,16 @@ public final class BatteryService extends SystemService {
            if (!mUpdatesStopped) {
                mHealthInfo = info.legacy.legacy;
                mHealthInfo2p1 = info;
                if (mMotHealthService != null) {
                    try {
                        mBatteryModProps = mMotHealthService.getModBatteryProperties();
                        if (mBatteryModProps.modFlag > 0) {
                            mHealthInfo.batteryLevel = mBatteryModProps.batteryLevel;
                        }
                    } catch (RemoteException e) {
                        Slog.e(TAG, "getModBatteryProperties fail!");
                    }
                }
                // Process the new values.
                processValuesLocked(false);
                mLock.notifyAll(); // for any waiters on new info
@@ -491,6 +535,8 @@ public final class BatteryService extends SystemService {
            mPlugType = BatteryManager.BATTERY_PLUGGED_USB;
        } else if (mHealthInfo.chargerWirelessOnline) {
            mPlugType = BatteryManager.BATTERY_PLUGGED_WIRELESS;
        } else if (supplementalOrEmergencyModOnline()) {
            mPlugType = BatteryManager.BATTERY_PLUGGED_MOD;
        } else {
            mPlugType = BATTERY_PLUGGED_NONE;
        }
@@ -505,7 +551,7 @@ public final class BatteryService extends SystemService {
        // Let the battery stats keep track of the current level.
        try {
            mBatteryStats.setBatteryState(mHealthInfo.batteryStatus, mHealthInfo.batteryHealth,
                    mPlugType, mHealthInfo.batteryLevel, mHealthInfo.batteryTemperature,
                    maybeTranslatePlugType(mPlugType), mHealthInfo.batteryLevel, mHealthInfo.batteryTemperature,
                    mHealthInfo.batteryVoltage, mHealthInfo.batteryChargeCounter,
                    mHealthInfo.batteryFullCharge,
                    mHealthInfo2p1.batteryChargeTimeToFullNowSeconds);
@@ -526,7 +572,12 @@ public final class BatteryService extends SystemService {
                mHealthInfo.maxChargingCurrent != mLastMaxChargingCurrent ||
                mHealthInfo.maxChargingVoltage != mLastMaxChargingVoltage ||
                mHealthInfo.batteryChargeCounter != mLastChargeCounter ||
                mInvalidCharger != mLastInvalidCharger)) {
                mInvalidCharger != mLastInvalidCharger ||
                mBatteryModProps.modLevel != mLastModLevel ||
                mBatteryModProps.modStatus != mLastModStatus ||
                mBatteryModProps.modFlag != mLastModFlag ||
                mBatteryModProps.modType != mLastModType ||
                mBatteryModProps.modPowerSource != mLastModPowerSource)) {

            if (mPlugType != mLastPlugType) {
                if (mLastPlugType == BATTERY_PLUGGED_NONE) {
@@ -697,6 +748,12 @@ public final class BatteryService extends SystemService {
            mLastChargeCounter = mHealthInfo.batteryChargeCounter;
            mLastBatteryLevelCritical = mBatteryLevelCritical;
            mLastInvalidCharger = mInvalidCharger;
            mLastModLevel = mBatteryModProps.modLevel;
            mLastModStatus = mBatteryModProps.modStatus;
            mLastModFlag = mBatteryModProps.modFlag;
            mLastModType = mBatteryModProps.modType;
            mLastModPowerSource = mBatteryModProps.modPowerSource;

        }
    }

@@ -716,7 +773,7 @@ public final class BatteryService extends SystemService {
        intent.putExtra(BatteryManager.EXTRA_BATTERY_LOW, mSentLowBatteryBroadcast);
        intent.putExtra(BatteryManager.EXTRA_SCALE, BATTERY_SCALE);
        intent.putExtra(BatteryManager.EXTRA_ICON_SMALL, icon);
        intent.putExtra(BatteryManager.EXTRA_PLUGGED, mPlugType);
        intent.putExtra(BatteryManager.EXTRA_PLUGGED, maybeTranslatePlugType(mPlugType));
        intent.putExtra(BatteryManager.EXTRA_VOLTAGE, mHealthInfo.batteryVoltage);
        intent.putExtra(BatteryManager.EXTRA_TEMPERATURE, mHealthInfo.batteryTemperature);
        intent.putExtra(BatteryManager.EXTRA_TECHNOLOGY, mHealthInfo.batteryTechnology);
@@ -724,6 +781,12 @@ public final class BatteryService extends SystemService {
        intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_CURRENT, mHealthInfo.maxChargingCurrent);
        intent.putExtra(BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE, mHealthInfo.maxChargingVoltage);
        intent.putExtra(BatteryManager.EXTRA_CHARGE_COUNTER, mHealthInfo.batteryChargeCounter);
        intent.putExtra(BatteryManager.EXTRA_MOD_LEVEL, mBatteryModProps.modLevel);
        intent.putExtra(BatteryManager.EXTRA_MOD_STATUS, mBatteryModProps.modStatus);
        intent.putExtra(BatteryManager.EXTRA_MOD_FLAG, mBatteryModProps.modFlag);
        intent.putExtra(BatteryManager.EXTRA_PLUGGED_RAW, mPlugType);
        intent.putExtra(BatteryManager.EXTRA_MOD_TYPE, mBatteryModProps.modType);
        intent.putExtra(BatteryManager.EXTRA_MOD_POWER_SOURCE, mBatteryModProps.modPowerSource);
        if (DEBUG) {
            Slog.d(TAG, "Sending ACTION_BATTERY_CHANGED. scale:" + BATTERY_SCALE
                    + ", info:" + mHealthInfo.toString());
@@ -862,6 +925,36 @@ public final class BatteryService extends SystemService {
        }
    }

    private int maybeTranslatePlugType(int plugType) {
        if (plugType != BatteryManager.BATTERY_PLUGGED_MOD) {
            return plugType;
        }
        if (this.mHealthInfo.batteryStatus == BatteryManager.BATTERY_STATUS_CHARGING) {
            return 1;
        }
        return 0;
    }

    private boolean supplementalOrEmergencyModOnline() {
        return mBatteryModProps.modLevel > 0 &&
        (mBatteryModProps.modType == MOD_TYPE_SUPPLEMENTAL ||
        mBatteryModProps.modType == MOD_TYPE_EMERGENCY);
    }

    private boolean isModBatteryActive() {
        if (mBatteryModProps.modLevel <= 0 || mBatteryModProps.modType != MOD_TYPE_SUPPLEMENTAL) {
            return false;
        }
        String batteryMode = SystemProperties.get("sys.mod.batterymode");
        if ("0".equals(batteryMode)) {
            return true;
        }
        if (!"2".equals(batteryMode) && mHealthInfo.batteryLevel <= 80) {
            return true;
        }
        return false;
    }

    class Shell extends ShellCommand {
        @Override
        public int onCommand(String cmd) {