Add WakeLock.setStateListener() API.
WakeLock uses this API to add listener of type WakelockStateListener, whenever framework enable/disable this wake lock, the onStateChanged() callback on this listener is called. This API can be called before or afte acquiring the wakelock. It can be called multiple times to change to another listener. Add test cases testNotifyWakeLockCallback() and testNotifyWakeLockCallbackChange() in PowerManagerServiceTest.java. Bug: 213925462 Test: atest cts/tests/tests/os/src/android/os/cts/PowerManager_WakeLockTest.java. Change-Id: Ic59303c59e53eb974e2765e3036002ac97ce8aa5
This commit is contained in:
@@ -31729,9 +31729,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();
|
||||
|
||||
@@ -128,6 +128,7 @@ filegroup {
|
||||
"android/os/IThermalStatusListener.aidl",
|
||||
"android/os/IThermalService.aidl",
|
||||
"android/os/IPowerManager.aidl",
|
||||
"android/os/IWakeLockCallback.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);
|
||||
|
||||
24
core/java/android/os/IWakeLockCallback.aidl
Normal file
24
core/java/android/os/IWakeLockCallback.aidl
Normal file
@@ -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);
|
||||
}
|
||||
@@ -2769,6 +2769,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.
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 {
|
||||
onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag);
|
||||
} 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);
|
||||
newWorkSource, newHistoryTag, newCallback /* notify the new callback */);
|
||||
} else {
|
||||
onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource, historyTag,
|
||||
callback);
|
||||
onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
|
||||
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) {
|
||||
|
||||
@@ -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
|
||||
@@ -5462,6 +5518,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();
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,11 +150,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
|
||||
@@ -167,7 +167,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
|
||||
@@ -186,7 +186,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);
|
||||
@@ -202,7 +202,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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user