Loading api/current.txt +5 −5 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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"; Loading @@ -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 { core/java/android/os/PowerManager.java +58 −39 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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(); Loading core/tests/coretests/src/android/os/PowerManagerTest.java +54 −14 Original line number Diff line number Diff line Loading @@ -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; /** Loading Loading @@ -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; Loading @@ -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); } } Loading
api/current.txt +5 −5 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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"; Loading @@ -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 {
core/java/android/os/PowerManager.java +58 −39 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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(); Loading @@ -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(); Loading
core/tests/coretests/src/android/os/PowerManagerTest.java +54 −14 Original line number Diff line number Diff line Loading @@ -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; /** Loading Loading @@ -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; Loading @@ -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); } }