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

Commit 52b40ae2 authored by Wei Wang's avatar Wei Wang Committed by Android (Google) Code Review
Browse files

Merge "Address API review comments for Thermal API"

parents e8dfaf75 7a49ff6c
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -35118,6 +35118,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();
@@ -35129,8 +35131,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";
@@ -35155,9 +35156,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);
    }
}