summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/api/current.txt5
-rw-r--r--core/java/Android.bp1
-rw-r--r--core/java/android/os/IPowerManager.aidl6
-rw-r--r--core/java/android/os/IWakeLockCallback.aidl24
-rw-r--r--core/java/android/os/PowerManager.java60
-rw-r--r--services/core/java/com/android/server/power/Notifier.java38
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java148
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java86
9 files changed, 317 insertions, 61 deletions
diff --git a/core/api/current.txt b/core/api/current.txt
index 19830c3990a1..5a293c52bdd4 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -31738,9 +31738,14 @@ package android.os {
method public void release();
method public void release(int);
method public void setReferenceCounted(boolean);
+ method public void setStateListener(@NonNull java.util.concurrent.Executor, @Nullable android.os.PowerManager.WakeLockStateListener);
method public void setWorkSource(android.os.WorkSource);
}
+ public static interface PowerManager.WakeLockStateListener {
+ method public void onStateChanged(boolean);
+ }
+
public class Process {
ctor public Process();
method public static final long getElapsedCpuTime();
diff --git a/core/java/Android.bp b/core/java/Android.bp
index 8234f03100ca..5649c5f1f7db 100644
--- a/core/java/Android.bp
+++ b/core/java/Android.bp
@@ -128,6 +128,7 @@ filegroup {
"android/os/IThermalStatusListener.aidl",
"android/os/IThermalService.aidl",
"android/os/IPowerManager.aidl",
+ "android/os/IWakeLockCallback.aidl",
],
}
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index df5b7bc237df..4fe6524dee27 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -21,15 +21,16 @@ import android.os.BatterySaverPolicyConfig;
import android.os.ParcelDuration;
import android.os.PowerSaveState;
import android.os.WorkSource;
+import android.os.IWakeLockCallback;
/** @hide */
interface IPowerManager
{
void acquireWakeLock(IBinder lock, int flags, String tag, String packageName, in WorkSource ws,
- String historyTag, int displayId);
+ String historyTag, int displayId, IWakeLockCallback callback);
void acquireWakeLockWithUid(IBinder lock, int flags, String tag, String packageName,
- int uidtoblame, int displayId);
+ int uidtoblame, int displayId, IWakeLockCallback callback);
@UnsupportedAppUsage
void releaseWakeLock(IBinder lock, int flags);
void updateWakeLockUids(IBinder lock, in int[] uids);
@@ -40,6 +41,7 @@ interface IPowerManager
boolean setPowerModeChecked(int mode, boolean enabled);
void updateWakeLockWorkSource(IBinder lock, in WorkSource ws, String historyTag);
+ void updateWakeLockCallback(IBinder lock, IWakeLockCallback callback);
boolean isWakeLockLevelSupported(int level);
void userActivity(int displayId, long time, int event, int flags);
diff --git a/core/java/android/os/IWakeLockCallback.aidl b/core/java/android/os/IWakeLockCallback.aidl
new file mode 100644
index 000000000000..89615d22421e
--- /dev/null
+++ b/core/java/android/os/IWakeLockCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+/**
+ * @hide
+ */
+oneway interface IWakeLockCallback {
+ oneway void onStateChanged(boolean enabled);
+}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 5bd8588d8970..315eef78724e 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -2770,6 +2770,23 @@ public final class PowerManager {
public static final int PRE_IDLE_TIMEOUT_MODE_SHORT = 2;
/**
+ * A listener interface to get notified when the wakelock is enabled/disabled.
+ */
+ public interface WakeLockStateListener {
+ /**
+ * Frameworks could disable the wakelock because either device's power allowlist has
+ * changed, or the app's wakelock has exceeded its quota, or the app goes into cached
+ * state.
+ * <p>
+ * This callback is called whenever the wakelock's state has changed.
+ * </p>
+ *
+ * @param enabled true is enabled, false is disabled.
+ */
+ void onStateChanged(boolean enabled);
+ }
+
+ /**
* A wake lock is a mechanism to indicate that your application needs
* to have the device stay on.
* <p>
@@ -2800,6 +2817,8 @@ public final class PowerManager {
private String mHistoryTag;
private final String mTraceName;
private final int mDisplayId;
+ private WakeLockStateListener mListener;
+ private IWakeLockCallback mCallback;
private final Runnable mReleaser = () -> release(RELEASE_FLAG_TIMEOUT);
@@ -2890,7 +2909,7 @@ public final class PowerManager {
Trace.asyncTraceBegin(Trace.TRACE_TAG_POWER, mTraceName, 0);
try {
mService.acquireWakeLock(mToken, mFlags, mTag, mPackageName, mWorkSource,
- mHistoryTag, mDisplayId);
+ mHistoryTag, mDisplayId, mCallback);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3083,6 +3102,45 @@ public final class PowerManager {
}
};
}
+
+ /**
+ * Set the listener to get notified when the wakelock is enabled/disabled.
+ *
+ * @param executor {@link Executor} to handle listener callback.
+ * @param listener listener to be added, set the listener to null to cancel a listener.
+ */
+ public void setStateListener(@NonNull @CallbackExecutor Executor executor,
+ @Nullable WakeLockStateListener listener) {
+ Preconditions.checkNotNull(executor, "executor cannot be null");
+ synchronized (mToken) {
+ if (listener != mListener) {
+ mListener = listener;
+ if (listener != null) {
+ mCallback = new IWakeLockCallback.Stub() {
+ public void onStateChanged(boolean enabled) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> {
+ listener.onStateChanged(enabled);
+ });
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+ };
+ } else {
+ mCallback = null;
+ }
+ if (mHeld) {
+ try {
+ mService.updateWakeLockCallback(mToken, mCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+ }
}
/**
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 73ec2cd66ac1..77d63100032c 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -33,6 +33,7 @@ import android.metrics.LogMaker;
import android.net.Uri;
import android.os.BatteryStats;
import android.os.Handler;
+import android.os.IWakeLockCallback;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -215,14 +216,15 @@ public class Notifier {
* Called when a wake lock is acquired.
*/
public void onWakeLockAcquired(int flags, String tag, String packageName,
- int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
+ int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
+ IWakeLockCallback callback) {
if (DEBUG) {
Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
+ "\", packageName=" + packageName
+ ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
+ ", workSource=" + workSource);
}
-
+ notifyWakeLockListener(callback, true);
final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
if (monitorType >= 0) {
try {
@@ -300,8 +302,9 @@ public class Notifier {
*/
public void onWakeLockChanging(int flags, String tag, String packageName,
int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
- int newFlags, String newTag, String newPackageName, int newOwnerUid,
- int newOwnerPid, WorkSource newWorkSource, String newHistoryTag) {
+ IWakeLockCallback callback, int newFlags, String newTag, String newPackageName,
+ int newOwnerUid, int newOwnerPid, WorkSource newWorkSource, String newHistoryTag,
+ IWakeLockCallback newCallback) {
final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
@@ -323,10 +326,16 @@ public class Notifier {
} catch (RemoteException ex) {
// Ignore
}
+ } else if (!PowerManagerService.isSameCallback(callback, newCallback)) {
+ onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
+ null /* Do not notify the old callback */);
+ onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
+ newWorkSource, newHistoryTag, newCallback /* notify the new callback */);
} else {
- onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag);
+ onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
+ callback);
onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
- newWorkSource, newHistoryTag);
+ newWorkSource, newHistoryTag, newCallback);
}
}
@@ -334,14 +343,15 @@ public class Notifier {
* Called when a wake lock is released.
*/
public void onWakeLockReleased(int flags, String tag, String packageName,
- int ownerUid, int ownerPid, WorkSource workSource, String historyTag) {
+ int ownerUid, int ownerPid, WorkSource workSource, String historyTag,
+ IWakeLockCallback callback) {
if (DEBUG) {
Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
+ "\", packageName=" + packageName
+ ", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
+ ", workSource=" + workSource);
}
-
+ notifyWakeLockListener(callback, false);
final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
if (monitorType >= 0) {
try {
@@ -859,6 +869,18 @@ public class Notifier {
return enabled && dndOff;
}
+ private void notifyWakeLockListener(IWakeLockCallback callback, boolean isEnabled) {
+ if (callback != null) {
+ mHandler.post(() -> {
+ try {
+ callback.onStateChanged(isEnabled);
+ } catch (RemoteException e) {
+ throw new IllegalArgumentException("Wakelock.mCallback is already dead.", e);
+ }
+ });
+ }
+ }
+
private final class NotifierHandler extends Handler {
public NotifierHandler(Looper looper) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index efcfbdd16e4e..38570727742d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -66,6 +66,7 @@ import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IBinder;
import android.os.IPowerManager;
+import android.os.IWakeLockCallback;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelDuration;
@@ -1436,7 +1437,8 @@ public final class PowerManagerService extends SystemService
}
private void acquireWakeLockInternal(IBinder lock, int displayId, int flags, String tag,
- String packageName, WorkSource ws, String historyTag, int uid, int pid) {
+ String packageName, WorkSource ws, String historyTag, int uid, int pid,
+ @Nullable IWakeLockCallback callback) {
synchronized (mLock) {
if (displayId != Display.INVALID_DISPLAY) {
final DisplayInfo displayInfo =
@@ -1460,11 +1462,12 @@ public final class PowerManagerService extends SystemService
boolean notifyAcquire;
if (index >= 0) {
wakeLock = mWakeLocks.get(index);
- if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
+ if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid, callback)) {
// Update existing wake lock. This shouldn't happen but is harmless.
notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,
- uid, pid, ws, historyTag);
- wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
+ uid, pid, ws, historyTag, callback);
+ wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid,
+ callback);
}
notifyAcquire = false;
} else {
@@ -1476,12 +1479,7 @@ public final class PowerManagerService extends SystemService
}
state.mNumWakeLocks++;
wakeLock = new WakeLock(lock, displayId, flags, tag, packageName, ws, historyTag,
- uid, pid, state);
- try {
- lock.linkToDeath(wakeLock, 0);
- } catch (RemoteException ex) {
- throw new IllegalArgumentException("Wake lock is already dead.");
- }
+ uid, pid, state, callback);
mWakeLocks.add(wakeLock);
setWakeLockDisabledStateLocked(wakeLock);
notifyAcquire = true;
@@ -1576,11 +1574,8 @@ public final class PowerManagerService extends SystemService
mRequestWaitForNegativeProximity = true;
}
- try {
- wakeLock.mLock.unlinkToDeath(wakeLock, 0);
- } catch (NoSuchElementException e) {
- Slog.wtf(TAG, "Failed to unlink wakelock", e);
- }
+ wakeLock.unlinkToDeath();
+ wakeLock.setDisabled(true);
removeWakeLockLocked(wakeLock, index);
}
}
@@ -1650,13 +1645,41 @@ public final class PowerManagerService extends SystemService
if (!wakeLock.hasSameWorkSource(ws)) {
notifyWakeLockChangingLocked(wakeLock, wakeLock.mFlags, wakeLock.mTag,
wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
- ws, historyTag);
+ ws, historyTag, null);
wakeLock.mHistoryTag = historyTag;
wakeLock.updateWorkSource(ws);
}
}
}
+ private void updateWakeLockCallbackInternal(IBinder lock, IWakeLockCallback callback,
+ int callingUid) {
+ synchronized (mLock) {
+ int index = findWakeLockIndexLocked(lock);
+ if (index < 0) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "updateWakeLockCallbackInternal: lock=" + Objects.hashCode(lock)
+ + " [not found]");
+ }
+ throw new IllegalArgumentException("Wake lock not active: " + lock
+ + " from uid " + callingUid);
+ }
+
+ WakeLock wakeLock = mWakeLocks.get(index);
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "updateWakeLockCallbackInternal: lock=" + Objects.hashCode(lock)
+ + " [" + wakeLock.mTag + "]");
+ }
+
+ if (!isSameCallback(callback, wakeLock.mCallback)) {
+ notifyWakeLockChangingLocked(wakeLock, wakeLock.mFlags, wakeLock.mTag,
+ wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
+ wakeLock.mWorkSource, wakeLock.mHistoryTag, callback);
+ wakeLock.mCallback = callback;
+ }
+ }
+ }
+
@GuardedBy("mLock")
private int findWakeLockIndexLocked(IBinder lock) {
final int count = mWakeLocks.size();
@@ -1684,7 +1707,7 @@ public final class PowerManagerService extends SystemService
wakeLock.mNotifiedAcquired = true;
mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
- wakeLock.mHistoryTag);
+ wakeLock.mHistoryTag, wakeLock.mCallback);
restartNofifyLongTimerLocked(wakeLock);
}
}
@@ -1726,11 +1749,13 @@ public final class PowerManagerService extends SystemService
@GuardedBy("mLock")
private void notifyWakeLockChangingLocked(WakeLock wakeLock, int flags, String tag,
- String packageName, int uid, int pid, WorkSource ws, String historyTag) {
+ String packageName, int uid, int pid, WorkSource ws, String historyTag,
+ IWakeLockCallback callback) {
if (mSystemReady && wakeLock.mNotifiedAcquired) {
mNotifier.onWakeLockChanging(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
- wakeLock.mHistoryTag, flags, tag, packageName, uid, pid, ws, historyTag);
+ wakeLock.mHistoryTag, wakeLock.mCallback, flags, tag, packageName, uid, pid, ws,
+ historyTag, callback);
notifyWakeLockLongFinishedLocked(wakeLock);
// Changing the wake lock will count as releasing the old wake lock(s) and
// acquiring the new ones... we do this because otherwise once a wakelock
@@ -1747,7 +1772,7 @@ public final class PowerManagerService extends SystemService
wakeLock.mAcquireTime = 0;
mNotifier.onWakeLockReleased(wakeLock.mFlags, wakeLock.mTag,
wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
- wakeLock.mWorkSource, wakeLock.mHistoryTag);
+ wakeLock.mWorkSource, wakeLock.mHistoryTag, wakeLock.mCallback);
notifyWakeLockLongFinishedLocked(wakeLock);
}
}
@@ -4045,10 +4070,7 @@ public final class PowerManagerService extends SystemService
}
}
}
- if (wakeLock.mDisabled != disabled) {
- wakeLock.mDisabled = disabled;
- return true;
- }
+ return wakeLock.setDisabled(disabled);
}
return false;
}
@@ -5041,10 +5063,11 @@ public final class PowerManagerService extends SystemService
public boolean mNotifiedAcquired;
public boolean mNotifiedLong;
public boolean mDisabled;
+ public IWakeLockCallback mCallback;
public WakeLock(IBinder lock, int displayId, int flags, String tag, String packageName,
WorkSource workSource, String historyTag, int ownerUid, int ownerPid,
- UidState uidState) {
+ UidState uidState, @Nullable IWakeLockCallback callback) {
mLock = lock;
mDisplayId = displayId;
mFlags = flags;
@@ -5055,15 +5078,43 @@ public final class PowerManagerService extends SystemService
mOwnerUid = ownerUid;
mOwnerPid = ownerPid;
mUidState = uidState;
+ mCallback = callback;
+ linkToDeath();
}
@Override
public void binderDied() {
+ unlinkToDeath();
PowerManagerService.this.handleWakeLockDeath(this);
}
+ private void linkToDeath() {
+ try {
+ mLock.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ throw new IllegalArgumentException("Wakelock.mLock is already dead.");
+ }
+ }
+
+ @GuardedBy("mLock")
+ void unlinkToDeath() {
+ try {
+ mLock.unlinkToDeath(this, 0);
+ } catch (NoSuchElementException e) {
+ Slog.wtf(TAG, "Failed to unlink Wakelock.mLock", e);
+ }
+ }
+
+ public boolean setDisabled(boolean disabled) {
+ if (mDisabled != disabled) {
+ mDisabled = disabled;
+ return true;
+ } else {
+ return false;
+ }
+ }
public boolean hasSameProperties(int flags, String tag, WorkSource workSource,
- int ownerUid, int ownerPid) {
+ int ownerUid, int ownerPid, IWakeLockCallback callback) {
return mFlags == flags
&& mTag.equals(tag)
&& hasSameWorkSource(workSource)
@@ -5072,7 +5123,8 @@ public final class PowerManagerService extends SystemService
}
public void updateProperties(int flags, String tag, String packageName,
- WorkSource workSource, String historyTag, int ownerUid, int ownerPid) {
+ WorkSource workSource, String historyTag, int ownerUid, int ownerPid,
+ IWakeLockCallback callback) {
if (!mPackageName.equals(packageName)) {
throw new IllegalStateException("Existing wake lock package name changed: "
+ mPackageName + " to " + packageName);
@@ -5089,6 +5141,7 @@ public final class PowerManagerService extends SystemService
mTag = tag;
updateWorkSource(workSource);
mHistoryTag = historyTag;
+ mCallback = callback;
}
public boolean hasSameWorkSource(WorkSource workSource) {
@@ -5307,11 +5360,12 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
- String packageName, int uid, int displayId) {
+ String packageName, int uid, int displayId, IWakeLockCallback callback) {
if (uid < 0) {
uid = Binder.getCallingUid();
}
- acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null, displayId);
+ acquireWakeLock(lock, flags, tag, packageName, new WorkSource(uid), null,
+ displayId, callback);
}
@Override // Binder call
@@ -5346,7 +5400,8 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void acquireWakeLock(IBinder lock, int flags, String tag, String packageName,
- WorkSource ws, String historyTag, int displayId) {
+ WorkSource ws, String historyTag, int displayId,
+ @Nullable IWakeLockCallback callback) {
if (lock == null) {
throw new IllegalArgumentException("lock must not be null");
}
@@ -5386,7 +5441,7 @@ public final class PowerManagerService extends SystemService
final long ident = Binder.clearCallingIdentity();
try {
acquireWakeLockInternal(lock, displayId, flags, tag, packageName, ws, historyTag,
- uid, pid);
+ uid, pid, callback);
} finally {
Binder.restoreCallingIdentity(ident);
}
@@ -5395,7 +5450,8 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public void acquireWakeLockAsync(IBinder lock, int flags, String tag, String packageName,
WorkSource ws, String historyTag) {
- acquireWakeLock(lock, flags, tag, packageName, ws, historyTag, Display.INVALID_DISPLAY);
+ acquireWakeLock(lock, flags, tag, packageName, ws, historyTag, Display.INVALID_DISPLAY,
+ null);
}
@Override // Binder call
@@ -5463,6 +5519,23 @@ public final class PowerManagerService extends SystemService
}
@Override // Binder call
+ public void updateWakeLockCallback(IBinder lock, IWakeLockCallback callback) {
+ if (lock == null) {
+ throw new IllegalArgumentException("lock must not be null");
+ }
+
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+
+ final int callingUid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ updateWakeLockCallbackInternal(lock, callback, callingUid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ @Override // Binder call
public boolean isWakeLockLevelSupported(int level) {
final long ident = Binder.clearCallingIdentity();
try {
@@ -6510,4 +6583,15 @@ public final class PowerManagerService extends SystemService
}
};
+ static boolean isSameCallback(IWakeLockCallback callback1,
+ IWakeLockCallback callback2) {
+ if (callback1 == callback2) {
+ return true;
+ }
+ if (callback1 != null && callback2 != null
+ && callback1.asBinder() == callback2.asBinder()) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index ceb723a407f9..33540c874c0a 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -160,11 +160,11 @@ public class VirtualDeviceManagerServiceTest {
mDeviceImpl.onVirtualDisplayCreatedLocked(displayId);
verify(mIPowerManagerMock, never()).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
- nullable(String.class), anyInt());
+ nullable(String.class), anyInt(), eq(null));
TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
- nullable(String.class), eq(displayId));
+ nullable(String.class), eq(displayId), eq(null));
}
@Test
@@ -177,7 +177,7 @@ public class VirtualDeviceManagerServiceTest {
TestableLooper.get(this).processAllMessages();
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(any(Binder.class), anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
- nullable(String.class), eq(displayId));
+ nullable(String.class), eq(displayId), eq(null));
}
@Test
@@ -196,7 +196,7 @@ public class VirtualDeviceManagerServiceTest {
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
- nullable(String.class), eq(displayId));
+ nullable(String.class), eq(displayId), eq(null));
IBinder wakeLock = wakeLockCaptor.getValue();
mDeviceImpl.onVirtualDisplayRemovedLocked(displayId);
@@ -212,7 +212,7 @@ public class VirtualDeviceManagerServiceTest {
verify(mIPowerManagerMock, Mockito.times(1)).acquireWakeLock(wakeLockCaptor.capture(),
anyInt(),
nullable(String.class), nullable(String.class), nullable(WorkSource.class),
- nullable(String.class), eq(displayId));
+ nullable(String.class), eq(displayId), eq(null));
IBinder wakeLock = wakeLockCaptor.getValue();
// Close the VirtualDevice without first notifying it of the VirtualDisplay removal.
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 51dbd97c183b..827349ad433a 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -64,6 +64,7 @@ import android.os.BatterySaverPolicyConfig;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
+import android.os.IWakeLockCallback;
import android.os.Looper;
import android.os.PowerManager;
import android.os.PowerSaveState;
@@ -102,6 +103,7 @@ import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.ArgumentMatcher;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
@@ -479,21 +481,21 @@ public class PowerManagerServiceTest {
// First, ensure that a normal full wake lock does not cause a wakeup
int flags = PowerManager.FULL_WAKE_LOCK;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
// Ensure that the flag does *NOT* work with a partial wake lock.
flags = PowerManager.PARTIAL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_ASLEEP);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
// Verify that flag forces a wakeup when paired to a FULL_WAKE_LOCK
flags = PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
}
@@ -661,12 +663,12 @@ public class PowerManagerServiceTest {
wakelockMap.put((String) inv.getArguments()[1], (int) inv.getArguments()[0]);
return null;
}).when(mNotifierMock).onWakeLockAcquired(anyInt(), anyString(), anyString(), anyInt(),
- anyInt(), any(), any());
+ anyInt(), any(), any(), any());
doAnswer(inv -> {
wakelockMap.remove((String) inv.getArguments()[1]);
return null;
}).when(mNotifierMock).onWakeLockReleased(anyInt(), anyString(), anyString(), anyInt(),
- anyInt(), any(), any());
+ anyInt(), any(), any(), any());
//
// TEST STARTS HERE
@@ -679,7 +681,7 @@ public class PowerManagerServiceTest {
// Create a wakelock
mService.getBinderServiceInstance().acquireWakeLock(new Binder(), flags, tag, pkg,
- null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
assertThat(wakelockMap.get(tag)).isEqualTo(flags); // Verify wakelock is active.
// Confirm that the wakelocks have been disabled when the forceSuspend is in flight.
@@ -737,7 +739,7 @@ public class PowerManagerServiceTest {
// Take a nap and verify we no longer hold the blocker
int flags = PowerManager.DOZE_WAKE_LOCK;
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
when(mDreamManagerInternalMock.isDreaming()).thenReturn(true);
mService.getBinderServiceInstance().goToSleep(mClock.now(),
PowerManager.GO_TO_SLEEP_REASON_APPLICATION, 0);
@@ -893,7 +895,7 @@ public class PowerManagerServiceTest {
mService.getBinderServiceInstance().acquireWakeLock(token,
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
- null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
advanceTime(60);
@@ -919,7 +921,7 @@ public class PowerManagerServiceTest {
mService.getBinderServiceInstance().acquireWakeLock(token,
PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, tag, pkg,
- null /* workSource */, null /* historyTag */, Display.DEFAULT_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.DEFAULT_DISPLAY, null);
advanceTime(1500);
mService.getBinderServiceInstance().releaseWakeLock(token, 0 /* flags */);
@@ -995,7 +997,7 @@ public class PowerManagerServiceTest {
mService.getBinderServiceInstance().acquireWakeLock(token,
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
- null /* workSource */, null /* historyTag */, Display.DEFAULT_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.DEFAULT_DISPLAY, null);
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
@@ -1035,7 +1037,7 @@ public class PowerManagerServiceTest {
mService.getBinderServiceInstance().acquireWakeLock(token,
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
- null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, null);
assertThat(mService.getGlobalWakefulnessLocked()).isEqualTo(WAKEFULNESS_AWAKE);
assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
@@ -1076,7 +1078,7 @@ public class PowerManagerServiceTest {
mService.getBinderServiceInstance().acquireWakeLock(token,
PowerManager.SCREEN_BRIGHT_WAKE_LOCK, tag, pkg,
- null /* workSource */, null /* historyTag */, nonDefaultDisplay);
+ null /* workSource */, null /* historyTag */, nonDefaultDisplay, null);
assertThat(mService.getWakefulnessLocked(Display.DEFAULT_DISPLAY_GROUP)).isEqualTo(
WAKEFULNESS_AWAKE);
@@ -1640,7 +1642,65 @@ public class PowerManagerServiceTest {
IBinder token = new Binder();
String packageName = "pkg.name";
mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
- null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY);
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY,
+ null /* callback */);
return mService.findWakeLockLocked(token);
}
+
+ /**
+ * Test IPowerManager.acquireWakeLock() with a IWakeLockCallback.
+ */
+ @Test
+ public void testNotifyWakeLockCallback() {
+ createService();
+ startSystem();
+ final String tag = "wakelock1";
+ final String packageName = "pkg.name";
+ final IBinder token = new Binder();
+ final int flags = PowerManager.PARTIAL_WAKE_LOCK;
+ final IWakeLockCallback callback = Mockito.mock(IWakeLockCallback.class);
+ final IBinder callbackBinder = Mockito.mock(Binder.class);
+ when(callback.asBinder()).thenReturn(callbackBinder);
+ mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, callback);
+ verify(mNotifierMock).onWakeLockAcquired(anyInt(), eq(tag), eq(packageName), anyInt(),
+ anyInt(), any(), any(), same(callback));
+
+ mService.getBinderServiceInstance().releaseWakeLock(token, 0);
+ verify(mNotifierMock).onWakeLockReleased(anyInt(), eq(tag), eq(packageName), anyInt(),
+ anyInt(), any(), any(), same(callback));
+ }
+
+ /**
+ * Test IPowerManager.updateWakeLockCallback() with a new IWakeLockCallback.
+ */
+ @Test
+ public void testNotifyWakeLockCallbackChange() {
+ createService();
+ startSystem();
+ final String tag = "wakelock1";
+ final String packageName = "pkg.name";
+ final IBinder token = new Binder();
+ int flags = PowerManager.PARTIAL_WAKE_LOCK;
+ final IWakeLockCallback callback1 = Mockito.mock(IWakeLockCallback.class);
+ final IBinder callbackBinder1 = Mockito.mock(Binder.class);
+ when(callback1.asBinder()).thenReturn(callbackBinder1);
+ mService.getBinderServiceInstance().acquireWakeLock(token, flags, tag, packageName,
+ null /* workSource */, null /* historyTag */, Display.INVALID_DISPLAY, callback1);
+ verify(mNotifierMock).onWakeLockAcquired(anyInt(), eq(tag), eq(packageName), anyInt(),
+ anyInt(), any(), any(), same(callback1));
+
+ final IWakeLockCallback callback2 = Mockito.mock(IWakeLockCallback.class);
+ final IBinder callbackBinder2 = Mockito.mock(Binder.class);
+ when(callback2.asBinder()).thenReturn(callbackBinder2);
+ mService.getBinderServiceInstance().updateWakeLockCallback(token, callback2);
+ verify(mNotifierMock).onWakeLockChanging(anyInt(), eq(tag), eq(packageName),
+ anyInt(), anyInt(), any(), any(), same(callback1),
+ anyInt(), eq(tag), eq(packageName), anyInt(), anyInt(), any(), any(),
+ same(callback2));
+
+ mService.getBinderServiceInstance().releaseWakeLock(token, 0);
+ verify(mNotifierMock).onWakeLockReleased(anyInt(), eq(tag), eq(packageName), anyInt(),
+ anyInt(), any(), any(), same(callback2));
+ }
}