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

Commit 7a49ff6c authored by Wei Wang's avatar Wei Wang
Browse files

Address API review comments for Thermal API

Bug: 126945111
Test: atest cts/tests/tests/os/src/android/os/cts/PowerManager_ThermalTest.java
Test: atest frameworks/base/core/tests/coretests/src/android/os/PowerManagerTest.java
Change-Id: I7ec1ea057b11c223c46d02ad63de335cb0a0d4dd
parent 79eb65c3
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -35114,6 +35114,8 @@ package android.os {
  }
  public final class PowerManager {
    method public void addThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
    method public void addThermalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.PowerManager.OnThermalStatusChangedListener);
    method public int getCurrentThermalStatus();
    method public int getLocationPowerSaveMode();
    method public boolean isDeviceIdleMode();
@@ -35125,8 +35127,7 @@ package android.os {
    method public boolean isWakeLockLevelSupported(int);
    method public android.os.PowerManager.WakeLock newWakeLock(int, String);
    method public void reboot(String);
    method public void registerThermalStatusCallback(@NonNull android.os.PowerManager.ThermalStatusCallback, @NonNull java.util.concurrent.Executor);
    method public void unregisterThermalStatusCallback(@NonNull android.os.PowerManager.ThermalStatusCallback);
    method public void removeThermalStatusListener(@NonNull android.os.PowerManager.OnThermalStatusChangedListener);
    field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
    field public static final String ACTION_DEVICE_IDLE_MODE_CHANGED = "android.os.action.DEVICE_IDLE_MODE_CHANGED";
    field public static final String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
@@ -35151,9 +35152,8 @@ package android.os {
    field public static final int THERMAL_STATUS_SHUTDOWN = 6; // 0x6
  }
  public abstract static class PowerManager.ThermalStatusCallback {
    ctor public PowerManager.ThermalStatusCallback();
    method public void onStatusChange(int);
  public static interface PowerManager.OnThermalStatusChangedListener {
    method public void onThermalStatusChanged(int);
  }
  public final class PowerManager.WakeLock {
+58 −39
Original line number Diff line number Diff line
@@ -809,7 +809,8 @@ public final class PowerManager {
    final Handler mHandler;

    IThermalService mThermalService;
    private ArrayMap<ThermalStatusCallback, IThermalStatusListener> mCallbackMap = new ArrayMap<>();
    private final ArrayMap<OnThermalStatusChangedListener, IThermalStatusListener>
            mListenerMap = new ArrayMap<>();

    IDeviceIdleController mIDeviceIdleController;

@@ -1769,51 +1770,73 @@ public final class PowerManager {
    }

    /**
     * Callback passed to
     * {@link PowerManager#registerThermalStatusCallback} and
     * {@link PowerManager#unregisterThermalStatusCallback}
     * to notify caller of thermal status.
     * Listener passed to
     * {@link PowerManager#addThermalStatusListener} and
     * {@link PowerManager#removeThermalStatusListener}
     * to notify caller of thermal status has changed.
     */
    public abstract static class ThermalStatusCallback {
    public interface OnThermalStatusChangedListener {

        /**
         * Called when overall thermal throttling status changed.
         * @param status defined in {@link android.os.Temperature}.
         */
        public void onStatusChange(@ThermalStatus int status) {}
        void onThermalStatusChanged(@ThermalStatus int status);
    }


    /**
     * This function registers a callback for thermal status change.
     * This function adds a listener for thermal status change, listen call back will be
     * enqueued tasks on the main thread
     *
     * @param callback callback to be registered.
     * @param executor {@link Executor} to handle the callbacks.
     * @param listener listener to be added,
     */
    public void registerThermalStatusCallback(
            @NonNull ThermalStatusCallback callback, @NonNull @CallbackExecutor Executor executor) {
        Preconditions.checkNotNull(callback, "callback cannnot be null");
        Preconditions.checkNotNull(executor, "executor cannnot be null");
    public void addThermalStatusListener(@NonNull OnThermalStatusChangedListener listener) {
        Preconditions.checkNotNull(listener, "listener cannot be null");
        synchronized (this) {
            if (mThermalService == null) {
                mThermalService = IThermalService.Stub.asInterface(
                        ServiceManager.getService(Context.THERMAL_SERVICE));
            }
            try {
                if (mCallbackMap.containsKey(callback)) {
                    throw new IllegalArgumentException("ThermalStatusCallback already registered");
            this.addThermalStatusListener(mContext.getMainExecutor(), listener);
        }
    }

    /**
     * This function adds a listener for thermal status change.
     *
     * @param executor {@link Executor} to handle listener callback.
     * @param listener listener to be added.
     */
    public void addThermalStatusListener(@NonNull @CallbackExecutor Executor executor,
            @NonNull OnThermalStatusChangedListener listener) {
        Preconditions.checkNotNull(listener, "listener cannot be null");
        Preconditions.checkNotNull(executor, "executor cannot be null");
        synchronized (this) {
            if (mThermalService == null) {
                mThermalService = IThermalService.Stub.asInterface(
                        ServiceManager.getService(Context.THERMAL_SERVICE));
            }
                IThermalStatusListener listener = new IThermalStatusListener.Stub() {
            Preconditions.checkArgument(!mListenerMap.containsKey(listener),
                    "Listener already registered: " + listener);
            IThermalStatusListener internalListener = new IThermalStatusListener.Stub() {
                @Override
                public void onStatusChange(int status) {
                    final long token = Binder.clearCallingIdentity();
                    try {
                        executor.execute(() -> {
                            callback.onStatusChange(status);
                            listener.onThermalStatusChanged(status);
                        });
                    } finally {
                        Binder.restoreCallingIdentity(token);
                    }
                }
            };
                if (mThermalService.registerThermalStatusListener(listener)) {
                    mCallbackMap.put(callback, listener);
            try {
                if (mThermalService.registerThermalStatusListener(internalListener)) {
                    mListenerMap.put(listener, internalListener);
                } else {
                    throw new RuntimeException("ThermalStatusCallback failed to register");
                    throw new RuntimeException("Listener failed to set");
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
@@ -1822,28 +1845,24 @@ public final class PowerManager {
    }

    /**
     * This function unregisters a callback for thermal status change.
     * This function removes a listener for thermal status change
     *
     * @param callback to be unregistered.
     *
     * see {@link #registerThermalStatusCallback}
     * @param listener listener to be removed
     */
    public void unregisterThermalStatusCallback(@NonNull ThermalStatusCallback callback) {
        Preconditions.checkNotNull(callback, "callback cannnot be null");
    public void removeThermalStatusListener(@NonNull OnThermalStatusChangedListener listener) {
        Preconditions.checkNotNull(listener, "listener cannot be null");
        synchronized (this) {
            if (mThermalService == null) {
                mThermalService = IThermalService.Stub.asInterface(
                        ServiceManager.getService(Context.THERMAL_SERVICE));
            }
            IThermalStatusListener internalListener = mListenerMap.get(listener);
            Preconditions.checkArgument(internalListener != null, "Listener was not added");
            try {
                IThermalStatusListener listener = mCallbackMap.get(callback);
                if (listener == null) {
                    throw new IllegalArgumentException("ThermalStatusCallback not registered");
                }
                if (mThermalService.unregisterThermalStatusListener(listener)) {
                    mCallbackMap.remove(callback);
                if (mThermalService.unregisterThermalStatusListener(internalListener)) {
                    mListenerMap.remove(listener);
                } else {
                    throw new RuntimeException("ThermalStatusCallback failed to unregister");
                    throw new RuntimeException("Listener failed to remove");
                }
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
+54 −14
Original line number Diff line number Diff line
@@ -41,7 +41,9 @@ public class PowerManagerTest extends AndroidTestCase {
    private UiDevice mUiDevice;
    private Executor mExec = Executors.newSingleThreadExecutor();
    @Mock
    private PowerManager.ThermalStatusCallback mCallback;
    private PowerManager.OnThermalStatusChangedListener mListener1;
    @Mock
    private PowerManager.OnThermalStatusChangedListener mListener2;
    private static final long CALLBACK_TIMEOUT_MILLI_SEC = 5000;

    /**
@@ -169,6 +171,11 @@ public class PowerManagerTest extends AndroidTestCase {
        // TODO: Threaded test (needs handler) to make sure timed wakelocks work too
    }

    /**
     * Confirm that we can get thermal status.
     *
     * @throws Exception
     */
    @Test
    public void testGetThermalStatus() throws Exception {
        int status = 0;
@@ -179,24 +186,57 @@ public class PowerManagerTest extends AndroidTestCase {
        assertEquals(status, mPm.getCurrentThermalStatus());
    }

    /**
     * Confirm that we can add/remove thermal status listener.
     *
     * @throws Exception
     */
    @Test
    public void testThermalStatusCallback() throws Exception {
        mPm.registerThermalStatusCallback(mCallback, mExec);
        verify(mCallback, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(1)).onStatusChange(0);
        reset(mCallback);
        int status = 3;
        // Initial override status is THERMAL_STATUS_NONE
        int status = PowerManager.THERMAL_STATUS_NONE;
        // Add listener1
        mPm.addThermalStatusListener(mExec, mListener1);
        verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(1)).onThermalStatusChanged(status);
        reset(mListener1);
        status = PowerManager.THERMAL_STATUS_SEVERE;
        mUiDevice.executeShellCommand("cmd thermalservice override-status "
                + Integer.toString(status));
        verify(mCallback, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(1)).onStatusChange(status);
        reset(mCallback);
        mPm.unregisterThermalStatusCallback(mCallback);
        status = 2;
        verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(1)).onThermalStatusChanged(status);
        reset(mListener1);
        // Add listener1 again
        try {
            mPm.addThermalStatusListener(mListener1);
            fail("Expected exception not thrown");
        } catch (IllegalArgumentException expectedException) {
        }
        // Add listener2 on main thread.
        mPm.addThermalStatusListener(mListener2);
        status = PowerManager.THERMAL_STATUS_MODERATE;
        mUiDevice.executeShellCommand("cmd thermalservice override-status "
                + Integer.toString(status));
        verify(mCallback, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(0)).onStatusChange(status);

        verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(1)).onThermalStatusChanged(status);
        verify(mListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(1)).onThermalStatusChanged(status);
        reset(mListener1);
        reset(mListener2);
        // Remove listener1
        mPm.removeThermalStatusListener(mListener1);
        // Remove listener1 again
        try {
            mPm.removeThermalStatusListener(mListener1);
            fail("Expected exception not thrown");
        } catch (IllegalArgumentException expectedException) {
        }
        status = PowerManager.THERMAL_STATUS_LIGHT;
        mUiDevice.executeShellCommand("cmd thermalservice override-status "
                + Integer.toString(status));
        verify(mListener1, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(0)).onThermalStatusChanged(status);
        verify(mListener2, timeout(CALLBACK_TIMEOUT_MILLI_SEC)
                .times(1)).onThermalStatusChanged(status);
    }
}