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

Commit c0e6469a authored by Xiang Wang's avatar Xiang Wang Committed by Android (Google) Code Review
Browse files

Merge changes from topic "v-thermal-headroom-thresholds" into main

* changes:
  Add NDK API AThermal_getThermalHeadroomThresholds
  Add getThermalHeadroomThresholds API
parents b1d2c0e6 5f4e819e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33179,6 +33179,7 @@ package android.os {
    method public int getCurrentThermalStatus();
    method public int getLocationPowerSaveMode();
    method public float getThermalHeadroom(@IntRange(from=0, to=60) int);
    method @FlaggedApi("android.os.allow_thermal_headroom_thresholds") @NonNull public java.util.Map<java.lang.Integer,java.lang.Float> getThermalHeadroomThresholds();
    method public boolean isAllowedInLowPowerStandby(int);
    method public boolean isAllowedInLowPowerStandby(@NonNull String);
    method public boolean isBatteryDischargePredictionPersonalized();
+5 −0
Original line number Diff line number Diff line
@@ -111,4 +111,9 @@ interface IThermalService {
     *     occur; returns NaN if the headroom or forecast is unavailable
     */
    float getThermalHeadroom(int forecastSeconds);

    /**
     * @return thermal headroom for each thermal status
     */
    float[] getThermalHeadroomThresholds();
}
+64 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.annotation.FlaggedApi;
import android.Manifest.permission;
import android.annotation.CallbackExecutor;
import android.annotation.CurrentTimeMillisLong;
import android.annotation.FlaggedApi;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
@@ -42,14 +43,17 @@ import android.view.Display;

import com.android.internal.util.Preconditions;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -1180,6 +1184,8 @@ public final class PowerManager {

    private final ArrayMap<OnThermalStatusChangedListener, IThermalStatusListener>
            mListenerMap = new ArrayMap<>();
    private final Object mThermalHeadroomThresholdsLock = new Object();
    private float[] mThermalHeadroomThresholds = null;

    /**
     * {@hide}
@@ -2636,6 +2642,7 @@ public final class PowerManager {
    public static final int THERMAL_STATUS_SHUTDOWN = Temperature.THROTTLING_SHUTDOWN;

    /** @hide */
    @Target(ElementType.TYPE_USE)
    @IntDef(prefix = { "THERMAL_STATUS_" }, value = {
            THERMAL_STATUS_NONE,
            THERMAL_STATUS_LIGHT,
@@ -2799,6 +2806,63 @@ public final class PowerManager {
        }
    }

    /**
     * Gets the thermal headroom thresholds for all available thermal throttling status above
     * {@link #THERMAL_STATUS_NONE}.
     * <p>
     * A thermal status key in the returned map is only set if the device manufacturer has the
     * corresponding threshold defined for at least one of its sensors. If it's set, one should
     * expect to see that from {@link #getCurrentThermalStatus()} or
     * {@link OnThermalStatusChangedListener#onThermalStatusChanged(int)}.
     * <p>
     * The headroom threshold is used to interpret the possible thermal throttling status based on
     * the headroom prediction. For example, if the headroom threshold for
     * {@link #THERMAL_STATUS_LIGHT} is 0.7, and a headroom prediction in 10s returns 0.75
     * (or {@code getThermalHeadroom(10)=0.75}), one can expect that in 10 seconds the system could
     * be in lightly throttled state if the workload remains the same. The app can consider
     * taking actions according to the nearest throttling status the difference between the headroom
     * and the threshold.
     * <p>
     * For new devices it's guaranteed to have a single sensor, but for older devices with multiple
     * sensors reporting different threshold values, the minimum threshold is taken to be
     * conservative on predictions. Thus, when reading real-time headroom, it's not guaranteed that
     * a real-time value of 0.75 (or {@code getThermalHeadroom(0)}=0.75) exceeding the threshold of
     * 0.7 above will always come with lightly throttled state
     * (or {@code getCurrentThermalStatus()=THERMAL_STATUS_LIGHT}) but it can be lower
     * (or {@code getCurrentThermalStatus()=THERMAL_STATUS_NONE}). While it's always guaranteed that
     * the device won't be throttled heavier than the unmet threshold's state, so a real-time
     * headroom of 0.75 will never come with {@link #THERMAL_STATUS_MODERATE} but lower, and 0.65
     * will never come with {@link #THERMAL_STATUS_LIGHT} but {@link #THERMAL_STATUS_NONE}.
     * <p>
     * The returned map of thresholds will not change between calls to this function, so it's
     * best to call this once on initialization. Modifying the result will not change the thresholds
     * cached by the system, and a new call to the API will get a new copy.
     *
     * @return map from each thermal status to its thermal headroom
     * @throws IllegalStateException if the thermal service is not ready
     * @throws UnsupportedOperationException if the feature is not enabled
     */
    @FlaggedApi(Flags.FLAG_ALLOW_THERMAL_HEADROOM_THRESHOLDS)
    public @NonNull Map<@ThermalStatus Integer, Float> getThermalHeadroomThresholds() {
        try {
            synchronized (mThermalHeadroomThresholdsLock) {
                if (mThermalHeadroomThresholds == null) {
                    mThermalHeadroomThresholds = mThermalService.getThermalHeadroomThresholds();
                }
                final ArrayMap<Integer, Float> ret = new ArrayMap<>(THERMAL_STATUS_SHUTDOWN);
                for (int status = THERMAL_STATUS_LIGHT; status <= THERMAL_STATUS_SHUTDOWN;
                        status++) {
                    if (!Float.isNaN(mThermalHeadroomThresholds[status])) {
                        ret.put(status, mThermalHeadroomThresholds[status]);
                    }
                }
                return ret;
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

    /**
     * If true, the doze component is not started until after the screen has been
     * turned off and the screen off animation has been performed.
+7 −0
Original line number Diff line number Diff line
@@ -28,6 +28,13 @@ flag {
    bug: "297542292"
}

flag {
    name: "allow_thermal_headroom_thresholds"
    namespace: "game"
    description: "Enable thermal headroom thresholds API"
    bug: "288119641"
}

flag {
    name: "allow_private_profile"
    namespace: "profile_experiences"
+10 −0
Original line number Diff line number Diff line
@@ -22,5 +22,15 @@
       ],
       "file_patterns": ["performance_hint.cpp"]
    }
  ],
  "postsubmit": [
    {
      "name": "CtsThermalTestCases",
       "file_patterns": ["thermal.cpp"]
    },
    {
      "name": "NativeThermalUnitTestCases",
       "file_patterns": ["thermal.cpp"]
    }
  ]
}
Loading