/*
*Copyright (c) 2016, The Linux Foundation. All rights reserved.
*
*Redistribution and use in source and binary forms, with or without
*modification, are permitted provided that the following conditions are
*met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
*THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
*WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
*MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
*ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
*BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
*CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
*SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
*OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
*IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.android.server.power;
import java.util.ArrayList;
import android.os.Binder;
import android.os.PowerManager;
import android.os.Process;
import android.util.Slog;
public final class QCNsrmPowerExtension {
static final String TAG = "QCNsrmPowerExtn";
static final boolean localLOGV = false;
private PowerManagerService pmHandle;
//track the blocked uids in PowerManagerService.
private final ArrayList<Integer> mPmsBlockedUids = new ArrayList<Integer>();
public QCNsrmPowerExtension (PowerManagerService handle) {
pmHandle = handle ;
}
protected void checkPmsBlockedWakelocks (
int uid, int pid, int flags,
String tag, PowerManagerService.WakeLock pMwakeLock
) {
if(mPmsBlockedUids.contains(new Integer(uid)) && uid != Process.myUid()) {
// wakelock acquisition for blocked uid, disable it.
if (localLOGV) {
Slog.d(TAG, "uid is blocked disabling wakeLock flags=0x" +
Integer.toHexString(flags) + " tag=" + tag + " uid=" +
uid + " pid =" + pid);
}
updatePmsBlockedWakelock(pMwakeLock, true);
}
}
private boolean checkWorkSourceObjectId (
int uid, PowerManagerService.WakeLock wl
) {
try {
for (int index = 0; index < wl.mWorkSource.size(); index++) {
if (uid == wl.mWorkSource.get(index)) {
if (localLOGV) Slog.v(TAG, "WS uid matched");
return true;
}
}
}
catch (Exception e) {
return false;
}
return false;
}
protected boolean processPmsBlockedUid (
int uid, boolean isBlocked,
ArrayList<PowerManagerService.WakeLock> mWakeLocks
) {
boolean changed = false;
if (updatePmsBlockedUidAllowed(uid, isBlocked))
return changed;
for (int index = 0; index < mWakeLocks.size(); index++) {
PowerManagerService.WakeLock wl = mWakeLocks.get(index);
if(wl != null) {
// update the wakelock for the blocked uid
if ((wl.mOwnerUid == uid || checkWorkSourceObjectId(uid, wl))
|| (wl.mTag.startsWith("*sync*") && wl.mOwnerUid ==
Process.SYSTEM_UID)) {
if(updatePmsBlockedWakelock(wl, isBlocked)) {
changed = true;
}
}
}
}
if(changed) {
pmHandle.mDirty |= pmHandle.DIRTY_WAKE_LOCKS;
pmHandle.updatePowerStateLocked();
}
return changed;
}
protected boolean updatePmsBlockedUidAllowed (
int uid, boolean isBlocked
) {
if (localLOGV) Slog.v(TAG, "updateBlockedUids: uid = " + uid +
"isBlocked = " + isBlocked);
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
if (localLOGV) Slog.v(TAG, "UpdateBlockedUids is not allowed");
return true;
}
updatePmsBlockedUids(uid, isBlocked);
return false;
}
private void updatePmsBlockedUids (int uid, boolean isBlocked) {
if(isBlocked) {
if (localLOGV) Slog.v(TAG, "adding powerMgr mPmBlockedUids "+
"with uid "+ uid);
mPmsBlockedUids.add(new Integer(uid));
}
else {
if (localLOGV) Slog.v(TAG, "clearing powerMgr mPmBlockedUids ");
mPmsBlockedUids.clear();
}
}
private boolean updatePmsBlockedWakelock (
PowerManagerService.WakeLock wakeLock, boolean update
) {
if (wakeLock != null && ((wakeLock.mFlags &
PowerManager.WAKE_LOCK_LEVEL_MASK
) == PowerManager.PARTIAL_WAKE_LOCK )) {
if (wakeLock.mDisabled != update && pmHandle != null) {
wakeLock.mDisabled = update;
if (localLOGV) Slog.v(TAG, "updatePmsBlockWakelock pmHandle "+pmHandle);
if (wakeLock.mDisabled) {
// This wake lock is no longer being respected.
pmHandle.notifyWakeLockReleasedLocked(wakeLock);
} else {
pmHandle.notifyWakeLockAcquiredLocked(wakeLock);
}
return true;
}
else {
if (localLOGV) Slog.v(TAG, "updatePmsBlockWakelock pmHandle "+pmHandle );
}
}
return false;
}
}