Merge \"Add reporting of long wake locks.\" into nyc-mr1-dev
am: ca37695ebc
Change-Id: I98b06d561945fddef5be4b749b5b2128b8622add
This commit is contained in:
@@ -1302,9 +1302,11 @@ public abstract class BatteryStats implements Parcelable {
|
||||
// Event for the UID that woke up the application processor.
|
||||
// Used for wakeups coming from WiFi, modem, etc.
|
||||
public static final int EVENT_WAKEUP_AP = 0x0013;
|
||||
// Event for reporting that a specific partial wake lock has been held for a long duration.
|
||||
public static final int EVENT_LONG_WAKE_LOCK = 0x0014;
|
||||
|
||||
// Number of event types.
|
||||
public static final int EVENT_COUNT = 0x0014;
|
||||
public static final int EVENT_COUNT = 0x0015;
|
||||
// Mask to extract out only the type part of the event.
|
||||
public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
|
||||
|
||||
@@ -1332,6 +1334,10 @@ public abstract class BatteryStats implements Parcelable {
|
||||
EVENT_TEMP_WHITELIST | EVENT_FLAG_START;
|
||||
public static final int EVENT_TEMP_WHITELIST_FINISH =
|
||||
EVENT_TEMP_WHITELIST | EVENT_FLAG_FINISH;
|
||||
public static final int EVENT_LONG_WAKE_LOCK_START =
|
||||
EVENT_LONG_WAKE_LOCK | EVENT_FLAG_START;
|
||||
public static final int EVENT_LONG_WAKE_LOCK_FINISH =
|
||||
EVENT_LONG_WAKE_LOCK | EVENT_FLAG_FINISH;
|
||||
|
||||
// For CMD_EVENT.
|
||||
public int eventCode;
|
||||
@@ -1996,13 +2002,13 @@ public abstract class BatteryStats implements Parcelable {
|
||||
public static final String[] HISTORY_EVENT_NAMES = new String[] {
|
||||
"null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
|
||||
"active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active", "tmpwhitelist",
|
||||
"screenwake", "wakeupap"
|
||||
"screenwake", "wakeupap", "longwake"
|
||||
};
|
||||
|
||||
public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
|
||||
"Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
|
||||
"Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa", "Etw",
|
||||
"Esw", "Ewa"
|
||||
"Esw", "Ewa", "Elw"
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -79,6 +79,8 @@ interface IBatteryStats {
|
||||
String newHistoryName, int newType, boolean newUnimportantForLogging);
|
||||
void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, String historyName,
|
||||
int type);
|
||||
void noteLongPartialWakelockStart(String name, String historyName, int uid);
|
||||
void noteLongPartialWakelockFinish(String name, String historyName, int uid);
|
||||
|
||||
void noteVibratorOn(int uid, long durationMillis);
|
||||
void noteVibratorOff(int uid);
|
||||
|
||||
@@ -3285,6 +3285,36 @@ public class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
}
|
||||
|
||||
public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
|
||||
uid = mapUid(uid);
|
||||
final long elapsedRealtime = mClocks.elapsedRealtime();
|
||||
final long uptime = mClocks.uptimeMillis();
|
||||
if (historyName == null) {
|
||||
historyName = name;
|
||||
}
|
||||
if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_START, historyName, uid,
|
||||
0)) {
|
||||
return;
|
||||
}
|
||||
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_START,
|
||||
historyName, uid);
|
||||
}
|
||||
|
||||
public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
|
||||
uid = mapUid(uid);
|
||||
final long elapsedRealtime = mClocks.elapsedRealtime();
|
||||
final long uptime = mClocks.uptimeMillis();
|
||||
if (historyName == null) {
|
||||
historyName = name;
|
||||
}
|
||||
if (!mActiveEvents.updateState(HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH, historyName, uid,
|
||||
0)) {
|
||||
return;
|
||||
}
|
||||
addHistoryEventLocked(elapsedRealtime, uptime, HistoryItem.EVENT_LONG_WAKE_LOCK_FINISH,
|
||||
historyName, uid);
|
||||
}
|
||||
|
||||
void aggregateLastWakeupUptimeLocked(long uptimeMs) {
|
||||
if (mLastWakeupReason != null) {
|
||||
long deltaUptime = uptimeMs - mLastWakeupUptimeMs;
|
||||
|
||||
@@ -484,6 +484,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
||||
}
|
||||
}
|
||||
|
||||
public void noteLongPartialWakelockStart(String name, String historyName, int uid) {
|
||||
enforceCallingPermission();
|
||||
synchronized (mStats) {
|
||||
mStats.noteLongPartialWakelockStart(name, historyName, uid);
|
||||
}
|
||||
}
|
||||
|
||||
public void noteLongPartialWakelockFinish(String name, String historyName, int uid) {
|
||||
enforceCallingPermission();
|
||||
synchronized (mStats) {
|
||||
mStats.noteLongPartialWakelockFinish(name, historyName, uid);
|
||||
}
|
||||
}
|
||||
|
||||
public void noteStartSensor(int uid, int sensor) {
|
||||
enforceCallingPermission();
|
||||
synchronized (mStats) {
|
||||
|
||||
@@ -194,6 +194,48 @@ final class Notifier {
|
||||
}
|
||||
}
|
||||
|
||||
public void onLongPartialWakeLockStart(String tag, int ownerUid, WorkSource workSource,
|
||||
String historyTag) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "onLongPartialWakeLockStart: ownerUid=" + ownerUid
|
||||
+ ", workSource=" + workSource);
|
||||
}
|
||||
|
||||
try {
|
||||
if (workSource != null) {
|
||||
final int N = workSource.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, workSource.get(i));
|
||||
}
|
||||
} else {
|
||||
mBatteryStats.noteLongPartialWakelockStart(tag, historyTag, ownerUid);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
public void onLongPartialWakeLockFinish(String tag, int ownerUid, WorkSource workSource,
|
||||
String historyTag) {
|
||||
if (DEBUG) {
|
||||
Slog.d(TAG, "onLongPartialWakeLockFinish: ownerUid=" + ownerUid
|
||||
+ ", workSource=" + workSource);
|
||||
}
|
||||
|
||||
try {
|
||||
if (workSource != null) {
|
||||
final int N = workSource.size();
|
||||
for (int i=0; i<N; i++) {
|
||||
mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, workSource.get(i));
|
||||
}
|
||||
} else {
|
||||
mBatteryStats.noteLongPartialWakelockFinish(tag, historyTag, ownerUid);
|
||||
}
|
||||
} catch (RemoteException ex) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a wake lock is changing.
|
||||
*/
|
||||
|
||||
@@ -56,6 +56,7 @@ import android.service.dreams.DreamManagerInternal;
|
||||
import android.service.vr.IVrManager;
|
||||
import android.service.vr.IVrStateCallbacks;
|
||||
import android.util.EventLog;
|
||||
import android.util.PrintWriterPrinter;
|
||||
import android.util.Slog;
|
||||
import android.util.SparseIntArray;
|
||||
import android.util.TimeUtils;
|
||||
@@ -73,9 +74,7 @@ import com.android.server.Watchdog;
|
||||
import com.android.server.am.BatteryStatsService;
|
||||
import com.android.server.lights.Light;
|
||||
import com.android.server.lights.LightsManager;
|
||||
import com.android.server.vr.VrManagerInternal;
|
||||
import com.android.server.vr.VrManagerService;
|
||||
import com.android.server.vr.VrStateListener;
|
||||
import libcore.util.Objects;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@@ -108,6 +107,8 @@ public final class PowerManagerService extends SystemService
|
||||
private static final int MSG_SANDMAN = 2;
|
||||
// Message: Sent when the screen brightness boost expires.
|
||||
private static final int MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 3;
|
||||
// Message: Polling to look for long held wake locks.
|
||||
private static final int MSG_CHECK_FOR_LONG_WAKELOCKS = 4;
|
||||
|
||||
// Dirty bit: mWakeLocks changed
|
||||
private static final int DIRTY_WAKE_LOCKS = 1 << 0;
|
||||
@@ -159,6 +160,9 @@ public final class PowerManagerService extends SystemService
|
||||
// This should perhaps be a setting.
|
||||
private static final int SCREEN_BRIGHTNESS_BOOST_TIMEOUT = 5 * 1000;
|
||||
|
||||
// How long a partial wake lock must be held until we consider it a long wake lock.
|
||||
static final long MIN_LONG_WAKE_CHECK_INTERVAL = 60*1000;
|
||||
|
||||
// Power hints defined in hardware/libhardware/include/hardware/power.h.
|
||||
private static final int POWER_HINT_LOW_POWER = 5;
|
||||
private static final int POWER_HINT_VR_MODE = 7;
|
||||
@@ -221,6 +225,15 @@ public final class PowerManagerService extends SystemService
|
||||
// A bitfield that summarizes the state of all active wakelocks.
|
||||
private int mWakeLockSummary;
|
||||
|
||||
// Have we scheduled a message to check for long wake locks? This is when we will check.
|
||||
private long mNotifyLongScheduled;
|
||||
|
||||
// Last time we checked for long wake locks.
|
||||
private long mNotifyLongDispatched;
|
||||
|
||||
// The time we decided to do next long check.
|
||||
private long mNotifyLongNextCheck;
|
||||
|
||||
// If true, instructs the display controller to wait for the proximity sensor to
|
||||
// go negative before turning the screen on.
|
||||
private boolean mRequestWaitForNegativeProximity;
|
||||
@@ -1025,6 +1038,38 @@ public final class PowerManagerService extends SystemService
|
||||
mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
|
||||
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
|
||||
wakeLock.mHistoryTag);
|
||||
restartNofifyLongTimerLocked(wakeLock);
|
||||
}
|
||||
}
|
||||
|
||||
private void enqueueNotifyLongMsgLocked(long time) {
|
||||
mNotifyLongScheduled = time;
|
||||
Message msg = mHandler.obtainMessage(MSG_CHECK_FOR_LONG_WAKELOCKS);
|
||||
msg.setAsynchronous(true);
|
||||
mHandler.sendMessageAtTime(msg, time);
|
||||
}
|
||||
|
||||
private void restartNofifyLongTimerLocked(WakeLock wakeLock) {
|
||||
wakeLock.mAcquireTime = SystemClock.uptimeMillis();
|
||||
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
|
||||
== PowerManager.PARTIAL_WAKE_LOCK && mNotifyLongScheduled == 0) {
|
||||
enqueueNotifyLongMsgLocked(wakeLock.mAcquireTime + MIN_LONG_WAKE_CHECK_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyWakeLockLongStartedLocked(WakeLock wakeLock) {
|
||||
if (mSystemReady && !wakeLock.mDisabled) {
|
||||
wakeLock.mNotifiedLong = true;
|
||||
mNotifier.onLongPartialWakeLockStart(wakeLock.mTag, wakeLock.mOwnerUid,
|
||||
wakeLock.mWorkSource, wakeLock.mHistoryTag);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyWakeLockLongFinishedLocked(WakeLock wakeLock) {
|
||||
if (wakeLock.mNotifiedLong) {
|
||||
wakeLock.mNotifiedLong = false;
|
||||
mNotifier.onLongPartialWakeLockFinish(wakeLock.mTag, wakeLock.mOwnerUid,
|
||||
wakeLock.mWorkSource, wakeLock.mHistoryTag);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1034,15 +1079,23 @@ public final class PowerManagerService extends SystemService
|
||||
mNotifier.onWakeLockChanging(wakeLock.mFlags, wakeLock.mTag, wakeLock.mPackageName,
|
||||
wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource,
|
||||
wakeLock.mHistoryTag, flags, tag, packageName, uid, pid, ws, historyTag);
|
||||
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
|
||||
// becomes long, if we just continued to treat it as long we can get in to
|
||||
// situations where we spam battery stats with every following change to it.
|
||||
restartNofifyLongTimerLocked(wakeLock);
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
|
||||
if (mSystemReady && wakeLock.mNotifiedAcquired) {
|
||||
wakeLock.mNotifiedAcquired = false;
|
||||
wakeLock.mAcquireTime = 0;
|
||||
mNotifier.onWakeLockReleased(wakeLock.mFlags, wakeLock.mTag,
|
||||
wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
|
||||
wakeLock.mWorkSource, wakeLock.mHistoryTag);
|
||||
notifyWakeLockLongFinishedLocked(wakeLock);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1599,6 +1652,42 @@ public final class PowerManagerService extends SystemService
|
||||
}
|
||||
}
|
||||
|
||||
void checkForLongWakeLocks() {
|
||||
synchronized (mLock) {
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
mNotifyLongDispatched = now;
|
||||
final long when = now - MIN_LONG_WAKE_CHECK_INTERVAL;
|
||||
long nextCheckTime = Long.MAX_VALUE;
|
||||
final int numWakeLocks = mWakeLocks.size();
|
||||
for (int i = 0; i < numWakeLocks; i++) {
|
||||
final WakeLock wakeLock = mWakeLocks.get(i);
|
||||
if ((wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK)
|
||||
== PowerManager.PARTIAL_WAKE_LOCK) {
|
||||
if (wakeLock.mNotifiedAcquired && !wakeLock.mNotifiedLong) {
|
||||
if (wakeLock.mAcquireTime < when) {
|
||||
// This wake lock has exceeded the long acquire time, report!
|
||||
notifyWakeLockLongStartedLocked(wakeLock);
|
||||
} else {
|
||||
// This wake lock could still become a long one, at this time.
|
||||
long checkTime = wakeLock.mAcquireTime + MIN_LONG_WAKE_CHECK_INTERVAL;
|
||||
if (checkTime < nextCheckTime) {
|
||||
nextCheckTime = checkTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mNotifyLongScheduled = 0;
|
||||
mHandler.removeMessages(MSG_CHECK_FOR_LONG_WAKELOCKS);
|
||||
if (nextCheckTime != Long.MAX_VALUE) {
|
||||
mNotifyLongNextCheck = nextCheckTime;
|
||||
enqueueNotifyLongMsgLocked(nextCheckTime);
|
||||
} else {
|
||||
mNotifyLongNextCheck = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the value of mUserActivitySummary to summarize the user requested
|
||||
* state of the system such as whether the screen should be bright or dim.
|
||||
@@ -2748,6 +2837,27 @@ public final class PowerManagerService extends SystemService
|
||||
pw.println(" mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
|
||||
pw.println(" mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
|
||||
pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
|
||||
pw.print(" mNotifyLongScheduled=");
|
||||
if (mNotifyLongScheduled == 0) {
|
||||
pw.print("(none)");
|
||||
} else {
|
||||
TimeUtils.formatDuration(mNotifyLongScheduled, SystemClock.uptimeMillis(), pw);
|
||||
}
|
||||
pw.println();
|
||||
pw.print(" mNotifyLongDispatched=");
|
||||
if (mNotifyLongDispatched == 0) {
|
||||
pw.print("(none)");
|
||||
} else {
|
||||
TimeUtils.formatDuration(mNotifyLongDispatched, SystemClock.uptimeMillis(), pw);
|
||||
}
|
||||
pw.println();
|
||||
pw.print(" mNotifyLongNextCheck=");
|
||||
if (mNotifyLongNextCheck == 0) {
|
||||
pw.print("(none)");
|
||||
} else {
|
||||
TimeUtils.formatDuration(mNotifyLongNextCheck, SystemClock.uptimeMillis(), pw);
|
||||
}
|
||||
pw.println();
|
||||
pw.println(" mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
|
||||
pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
|
||||
pw.println(" mSandmanScheduled=" + mSandmanScheduled);
|
||||
@@ -2855,6 +2965,10 @@ public final class PowerManagerService extends SystemService
|
||||
pw.print(": "); pw.println(mUidState.valueAt(i));
|
||||
}
|
||||
|
||||
pw.println();
|
||||
pw.println("Looper state:");
|
||||
mHandler.getLooper().dump(new PrintWriterPrinter(pw), " ");
|
||||
|
||||
pw.println();
|
||||
pw.println("Wake Locks: size=" + mWakeLocks.size());
|
||||
for (WakeLock wl : mWakeLocks) {
|
||||
@@ -2984,6 +3098,9 @@ public final class PowerManagerService extends SystemService
|
||||
case MSG_SCREEN_BRIGHTNESS_BOOST_TIMEOUT:
|
||||
handleScreenBrightnessBoostTimeout();
|
||||
break;
|
||||
case MSG_CHECK_FOR_LONG_WAKELOCKS:
|
||||
checkForLongWakeLocks();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3000,7 +3117,9 @@ public final class PowerManagerService extends SystemService
|
||||
public String mHistoryTag;
|
||||
public final int mOwnerUid;
|
||||
public final int mOwnerPid;
|
||||
public long mAcquireTime;
|
||||
public boolean mNotifiedAcquired;
|
||||
public boolean mNotifiedLong;
|
||||
public boolean mDisabled;
|
||||
|
||||
public WakeLock(IBinder lock, int flags, String tag, String packageName,
|
||||
@@ -3059,9 +3178,34 @@ public final class PowerManagerService extends SystemService
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getLockLevelString()
|
||||
+ " '" + mTag + "'" + getLockFlagsString() + (mDisabled ? " DISABLED" : "")
|
||||
+ " (uid=" + mOwnerUid + ", pid=" + mOwnerPid + ", ws=" + mWorkSource + ")";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(getLockLevelString());
|
||||
sb.append(" '");
|
||||
sb.append(mTag);
|
||||
sb.append("'");
|
||||
sb.append(getLockFlagsString());
|
||||
if (mDisabled) {
|
||||
sb.append(" DISABLED");
|
||||
}
|
||||
if (mNotifiedAcquired) {
|
||||
sb.append(" ACQ=");
|
||||
TimeUtils.formatDuration(mAcquireTime-SystemClock.uptimeMillis(), sb);
|
||||
}
|
||||
if (mNotifiedLong) {
|
||||
sb.append(" LONG");
|
||||
}
|
||||
sb.append(" (uid=");
|
||||
sb.append(mOwnerUid);
|
||||
if (mOwnerPid != 0) {
|
||||
sb.append(" pid=");
|
||||
sb.append(mOwnerPid);
|
||||
}
|
||||
if (mWorkSource != null) {
|
||||
sb.append(" ws=");
|
||||
sb.append(mWorkSource);
|
||||
}
|
||||
sb.append(")");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
|
||||
Reference in New Issue
Block a user