Reduce wake lock noise in battery history.

When the work source of a wake lock was changed, this would
cause the old wake lock to be released in battery stats before
the new one was acquired (the power manager would correctly
keep holding the associated wake lock).  This resulted in a
pointless entry in the battery history showing the last wake
lock being released and a new one acquired.

This change adds a new path in to battery stats to report
when a wake lock has changed, allowing it to acquire the
new wake locks first before the old ones, so it can't drop
down to zero wake locks.  This also provides better timing
information, as the same current time can be used for both
operations.

In addition, added a new kind of history entry for the
current time, so you can tell when in actual world clock
time the battery data is happening.

Change-Id: Ibbf2eed83bb93f31f60267889b7bc5b9e71e355f
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 0da77ea..7db4ac2 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -343,8 +343,9 @@
         }
 
         public class Pid {
-            public long mWakeSum;
-            public long mWakeStart;
+            public int mWakeNesting;
+            public long mWakeSumMs;
+            public long mWakeStartMs;
         }
 
         /**
@@ -515,7 +516,8 @@
         public static final byte CMD_UPDATE = 0;        // These can be written as deltas
         public static final byte CMD_NULL = -1;
         public static final byte CMD_START = 4;
-        public static final byte CMD_OVERFLOW = 5;
+        public static final byte CMD_CURRENT_TIME = 5;
+        public static final byte CMD_OVERFLOW = 6;
 
         public byte cmd = CMD_NULL;
         
@@ -610,6 +612,9 @@
         public int eventCode;
         public HistoryTag eventTag;
 
+        // Only set for CMD_CURRENT_TIME.
+        public long currentTime;
+
         // Meta-data when reading.
         public int numReadInts;
 
@@ -637,29 +642,28 @@
                     | ((((int)batteryLevel)<<8)&0xff00)
                     | ((((int)batteryStatus)<<16)&0xf0000)
                     | ((((int)batteryHealth)<<20)&0xf00000)
-                    | ((((int)batteryPlugType)<<24)&0xf000000);
+                    | ((((int)batteryPlugType)<<24)&0xf000000)
+                    | (wakelockTag != null ? 0x10000000 : 0)
+                    | (wakeReasonTag != null ? 0x20000000 : 0)
+                    | (eventCode != EVENT_NONE ? 0x40000000 : 0);
             dest.writeInt(bat);
             bat = (((int)batteryTemperature)&0xffff)
                     | ((((int)batteryVoltage)<<16)&0xffff0000);
             dest.writeInt(bat);
             dest.writeInt(states);
             if (wakelockTag != null) {
-                dest.writeInt(1);
                 wakelockTag.writeToParcel(dest, flags);
-            } else {
-                dest.writeInt(0);
             }
             if (wakeReasonTag != null) {
-                dest.writeInt(1);
                 wakeReasonTag.writeToParcel(dest, flags);
-            } else {
-                dest.writeInt(0);
             }
-            dest.writeInt(eventCode);
             if (eventCode != EVENT_NONE) {
                 dest.writeInt(eventCode);
                 eventTag.writeToParcel(dest, flags);
             }
+            if (cmd == CMD_CURRENT_TIME) {
+                dest.writeLong(currentTime);
+            }
         }
 
         public void readFromParcel(Parcel src) {
@@ -670,26 +674,34 @@
             batteryStatus = (byte)((bat>>16)&0xf);
             batteryHealth = (byte)((bat>>20)&0xf);
             batteryPlugType = (byte)((bat>>24)&0xf);
-            bat = src.readInt();
-            batteryTemperature = (short)(bat&0xffff);
-            batteryVoltage = (char)((bat>>16)&0xffff);
+            int bat2 = src.readInt();
+            batteryTemperature = (short)(bat2&0xffff);
+            batteryVoltage = (char)((bat2>>16)&0xffff);
             states = src.readInt();
-            if (src.readInt() != 0) {
+            if ((bat&0x10000000) != 0) {
                 wakelockTag = localWakelockTag;
                 wakelockTag.readFromParcel(src);
             } else {
                 wakelockTag = null;
             }
-            if (src.readInt() != 0) {
+            if ((bat&0x20000000) != 0) {
                 wakeReasonTag = localWakeReasonTag;
                 wakeReasonTag.readFromParcel(src);
             } else {
                 wakeReasonTag = null;
             }
-            eventCode = src.readInt();
-            if (eventCode != EVENT_NONE) {
+            if ((bat&0x40000000) != 0) {
+                eventCode = src.readInt();
                 eventTag = localEventTag;
                 eventTag.readFromParcel(src);
+            } else {
+                eventCode = EVENT_NONE;
+                eventTag = null;
+            }
+            if (cmd == CMD_CURRENT_TIME) {
+                currentTime = src.readLong();
+            } else {
+                currentTime = 0;
             }
             numReadInts += (src.dataPosition()-start)/4;
         }
@@ -749,6 +761,7 @@
             } else {
                 eventTag = null;
             }
+            currentTime = o.currentTime;
         }
 
         public boolean sameNonEvent(HistoryItem o) {
@@ -758,7 +771,8 @@
                     && batteryPlugType == o.batteryPlugType
                     && batteryTemperature == o.batteryTemperature
                     && batteryVoltage == o.batteryVoltage
-                    && states == o.states;
+                    && states == o.states
+                    && currentTime == o.currentTime;
         }
 
         public boolean same(HistoryItem o) {
@@ -2788,6 +2802,18 @@
                     pw.print(":");
                 }
                 pw.println("START");
+            } else if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
+                if (checkin) {
+                    pw.print(":");
+                }
+                pw.print("TIME:");
+                if (checkin) {
+                    pw.println(rec.currentTime);
+                } else {
+                    pw.print(" ");
+                    pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss",
+                            rec.currentTime).toString());
+                }
             } else if (rec.cmd == HistoryItem.CMD_OVERFLOW) {
                 if (checkin) {
                     pw.print(":");
@@ -2941,8 +2967,8 @@
                     }
                 }
                 pw.println();
+                oldState = rec.states;
             }
-            oldState = rec.states;
         }
     }
 
@@ -3059,8 +3085,8 @@
                             pw.println("Per-PID Stats:");
                             didPid = true;
                         }
-                        long time = pid.mWakeSum + (pid.mWakeStart != 0
-                                ? (nowRealtime - pid.mWakeStart) : 0);
+                        long time = pid.mWakeSumMs + (pid.mWakeNesting > 0
+                                ? (nowRealtime - pid.mWakeStartMs) : 0);
                         pw.print("  PID "); pw.print(pids.keyAt(j));
                                 pw.print(" wake time: ");
                                 TimeUtils.formatDuration(time, pw);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 3f90f76..5ba5c57 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -41,6 +41,9 @@
 
     void noteStartWakelockFromSource(in WorkSource ws, int pid, String name, String historyName,
             int type, boolean unimportantForLogging);
+    void noteChangeWakelockFromSource(in WorkSource ws, int pid, String name, int type,
+            in WorkSource newWs, int newPid, String newName,
+            String newHistoryName, int newType, boolean newUnimportantForLogging);
     void noteStopWakelockFromSource(in WorkSource ws, int pid, String name, int type);
 
     void noteVibratorOn(int uid, long durationMillis);
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index db21906..10fd2f0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -87,7 +87,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 98 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 99 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -2274,9 +2274,8 @@
     }
 
     public void noteStartWakeLocked(int uid, int pid, String name, String historyName, int type,
-            boolean unimportantForLogging) {
+            boolean unimportantForLogging, long elapsedRealtime) {
         uid = mapUid(uid);
-        final long elapsedRealtime = SystemClock.elapsedRealtime();
         if (type == WAKE_TYPE_PARTIAL) {
             // Only care about partial wake locks, since full wake locks
             // will be canceled when the user puts the screen to sleep.
@@ -2308,9 +2307,8 @@
         }
     }
 
-    public void noteStopWakeLocked(int uid, int pid, String name, int type) {
+    public void noteStopWakeLocked(int uid, int pid, String name, int type, long elapsedRealtime) {
         uid = mapUid(uid);
-        final long elapsedRealtime = SystemClock.elapsedRealtime();
         if (type == WAKE_TYPE_PARTIAL) {
             mWakeLockNesting--;
             if (mWakeLockNesting == 0) {
@@ -2328,16 +2326,37 @@
 
     public void noteStartWakeFromSourceLocked(WorkSource ws, int pid, String name,
             String historyName, int type, boolean unimportantForLogging) {
-        int N = ws.size();
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging);
+            noteStartWakeLocked(ws.get(i), pid, name, historyName, type, unimportantForLogging,
+                    elapsedRealtime);
+        }
+    }
+
+    public void noteChangeWakelockFromSourceLocked(WorkSource ws, int pid, String name, int type,
+            WorkSource newWs, int newPid, String newName,
+            String newHistoryName, int newType, boolean newUnimportantForLogging) {
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        // For correct semantics, we start the need worksources first, so that we won't
+        // make inappropriate history items as if all wake locks went away and new ones
+        // appeared.  This is okay because tracking of wake locks allows nesting.
+        final int NN = ws.size();
+        for (int i=0; i<NN; i++) {
+            noteStartWakeLocked(newWs.get(i), newPid, newName, newHistoryName, newType,
+                    newUnimportantForLogging, elapsedRealtime);
+        }
+        final int NO = ws.size();
+        for (int i=0; i<NO; i++) {
+            noteStopWakeLocked(ws.get(i), pid, name, type, elapsedRealtime);
         }
     }
 
     public void noteStopWakeFromSourceLocked(WorkSource ws, int pid, String name, int type) {
-        int N = ws.size();
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final int N = ws.size();
         for (int i=0; i<N; i++) {
-            noteStopWakeLocked(ws.get(i), pid, name, type);
+            noteStopWakeLocked(ws.get(i), pid, name, type, elapsedRealtime);
         }
     }
 
@@ -2466,7 +2485,7 @@
         if (u != null) {
             Uid.Pid p = u.mPids.get(pid);
             if (p != null) {
-                return p.mWakeSum + (p.mWakeStart != 0 ? (realtime - p.mWakeStart) : 0);
+                return p.mWakeSumMs + (p.mWakeNesting > 0 ? (realtime - p.mWakeStartMs) : 0);
             }
         }
         return 0;
@@ -2562,8 +2581,8 @@
 
             // Fake a wake lock, so we consider the device waked as long
             // as the screen is on.
-            noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false);
-            
+            noteStartWakeLocked(-1, -1, "screen", null, WAKE_TYPE_PARTIAL, false, elapsedRealtime);
+
             // Update discharge amounts.
             if (mOnBatteryInternal) {
                 updateDischargeScreenLevelsLocked(false, true);
@@ -2584,7 +2603,7 @@
                 mScreenBrightnessTimer[mScreenBrightnessBin].stopRunningLocked(elapsedRealtime);
             }
 
-            noteStopWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL);
+            noteStopWakeLocked(-1, -1, "screen", WAKE_TYPE_PARTIAL, elapsedRealtime);
 
             updateTimeBasesLocked(mOnBatteryTimeBase.isRunning(), true,
                     SystemClock.uptimeMillis() * 1000, elapsedRealtime * 1000);
@@ -3999,10 +4018,12 @@
                 mProcessStats.clear();
             }
             if (mPids.size() > 0) {
-                for (int i=0; !active && i<mPids.size(); i++) {
+                for (int i=mPids.size()-1; i>=0; i--) {
                     Pid pid = mPids.valueAt(i);
-                    if (pid.mWakeStart != 0) {
+                    if (pid.mWakeNesting > 0) {
                         active = true;
+                    } else {
+                        mPids.removeAt(i);
                     }
                 }
             }
@@ -4024,8 +4045,6 @@
                 mPackageStats.clear();
             }
 
-            mPids.clear();
-
             if (!active) {
                 if (mWifiRunningTimer != null) {
                     mWifiRunningTimer.detach();
@@ -4067,6 +4086,7 @@
                         mNetworkPacketActivityCounters[i].detach();
                     }
                 }
+                mPids.clear();
             }
 
             return !active;
@@ -5304,8 +5324,8 @@
             }
             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
                 Pid p = getPidStatsLocked(pid);
-                if (p.mWakeStart == 0) {
-                    p.mWakeStart = elapsedRealtimeMs;
+                if (p.mWakeNesting++ == 0) {
+                    p.mWakeStartMs = elapsedRealtimeMs;
                 }
             }
         }
@@ -5317,9 +5337,11 @@
             }
             if (pid >= 0 && type == WAKE_TYPE_PARTIAL) {
                 Pid p = mPids.get(pid);
-                if (p != null && p.mWakeStart != 0) {
-                    p.mWakeSum += elapsedRealtimeMs - p.mWakeStart;
-                    p.mWakeStart = 0;
+                if (p != null && p.mWakeNesting > 0) {
+                    if (p.mWakeNesting-- == 1) {
+                        p.mWakeSumMs += elapsedRealtimeMs - p.mWakeStartMs;
+                        p.mWakeStartMs = 0;
+                    }
                 }
             }
         }
@@ -5765,6 +5787,9 @@
             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
             if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
                     + Integer.toHexString(mHistoryCur.states));
+            mHistoryCur.currentTime = System.currentTimeMillis();
+            addHistoryBufferLocked(mSecRealtime, HistoryItem.CMD_CURRENT_TIME);
+            mHistoryCur.currentTime = 0;
             addHistoryRecordLocked(mSecRealtime);
             mDischargeCurrentLevel = mDischargeUnplugLevel = level;
             if (mScreenOn) {
@@ -6414,11 +6439,16 @@
             Slog.e("BatteryStats", "Error reading battery statistics", e);
         }
 
-        long now = SystemClock.elapsedRealtime();
-        if (USE_OLD_HISTORY) {
-            addHistoryRecordLocked(now, HistoryItem.CMD_START);
+        if (mHistoryBuffer.dataPosition() > 0) {
+            long now = SystemClock.elapsedRealtime();
+            if (USE_OLD_HISTORY) {
+                addHistoryRecordLocked(now, HistoryItem.CMD_START);
+            }
+            addHistoryBufferLocked(now, HistoryItem.CMD_START);
+            mHistoryCur.currentTime = System.currentTimeMillis();
+            addHistoryBufferLocked(now, HistoryItem.CMD_CURRENT_TIME);
+            mHistoryCur.currentTime = 0;
         }
-        addHistoryBufferLocked(now, HistoryItem.CMD_START);
     }
 
     public int describeContents() {
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index bda0183..9de3efe 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -426,8 +426,10 @@
         final Pair<String, ComponentName> mTarget;
         final BroadcastStats mBroadcastStats;
         final FilterStats mFilterStats;
+        final int mAlarmType;
 
-        InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource) {
+        InFlight(AlarmManagerService service, PendingIntent pendingIntent, WorkSource workSource,
+                int alarmType) {
             mPendingIntent = pendingIntent;
             mWorkSource = workSource;
             Intent intent = pendingIntent.getIntent();
@@ -441,6 +443,7 @@
                 mBroadcastStats.filterStats.put(mTarget, fs);
             }
             mFilterStats = fs;
+            mAlarmType = alarmType;
         }
     }
 
@@ -1280,17 +1283,12 @@
                             
                             // we have an active broadcast so stay awake.
                             if (mBroadcastRefCount == 0) {
-                                setWakelockWorkSource(alarm.operation, alarm.workSource);
-                                mWakeLock.setUnimportantForLogging(
-                                        alarm.operation == mTimeTickSender);
-                                mWakeLock.setHistoryTag(alarm.operation.getTag(
-                                        alarm.type == ELAPSED_REALTIME_WAKEUP
-                                                || alarm.type == RTC_WAKEUP
-                                                ? "*walarm*:" : "*alarm*:"));
+                                setWakelockWorkSource(alarm.operation, alarm.workSource,
+                                        alarm.type, true);
                                 mWakeLock.acquire();
                             }
                             final InFlight inflight = new InFlight(AlarmManagerService.this,
-                                    alarm.operation, alarm.workSource);
+                                    alarm.operation, alarm.workSource, alarm.type);
                             mInFlight.add(inflight);
                             mBroadcastRefCount++;
 
@@ -1345,9 +1343,17 @@
      * @param pi PendingIntent to attribute blame to if ws is null.
      * @param ws WorkSource to attribute blame.
      */
-    void setWakelockWorkSource(PendingIntent pi, WorkSource ws) {
+    void setWakelockWorkSource(PendingIntent pi, WorkSource ws, int type, boolean first) {
         try {
+            mWakeLock.setUnimportantForLogging(pi == mTimeTickSender);
             if (ws != null) {
+                if (first) {
+                    mWakeLock.setHistoryTag(pi.getTag(
+                            type == ELAPSED_REALTIME_WAKEUP || type == RTC_WAKEUP
+                                    ? "*walarm*:" : "*alarm*:"));
+                } else {
+                    mWakeLock.setHistoryTag(null);
+                }
                 mWakeLock.setWorkSource(ws);
                 return;
             }
@@ -1355,6 +1361,7 @@
             final int uid = ActivityManagerNative.getDefault()
                     .getUidForIntentSender(pi.getTarget());
             if (uid >= 0) {
+                mWakeLock.setHistoryTag(null);
                 mWakeLock.setWorkSource(new WorkSource(uid));
                 return;
             }
@@ -1579,7 +1586,8 @@
                     // the next of our alarms is now in flight.  reattribute the wakelock.
                     if (mInFlight.size() > 0) {
                         InFlight inFlight = mInFlight.get(0);
-                        setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource);
+                        setWakelockWorkSource(inFlight.mPendingIntent, inFlight.mWorkSource,
+                                inFlight.mAlarmType, false);
                     } else {
                         // should never happen
                         mLog.w("Alarm wakelock still held but sent queue empty");
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 39bfc23..3414daf 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -29,6 +29,7 @@
 import android.os.Parcel;
 import android.os.Process;
 import android.os.ServiceManager;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.telephony.SignalStrength;
@@ -133,14 +134,15 @@
             boolean unimportantForLogging) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging);
+            mStats.noteStartWakeLocked(uid, pid, name, historyName, type, unimportantForLogging,
+                    SystemClock.elapsedRealtime());
         }
     }
 
     public void noteStopWakelock(int uid, int pid, String name, int type) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteStopWakeLocked(uid, pid, name, type);
+            mStats.noteStopWakeLocked(uid, pid, name, type, SystemClock.elapsedRealtime());
         }
     }
 
@@ -153,6 +155,16 @@
         }
     }
 
+    public void noteChangeWakelockFromSource(WorkSource ws, int pid, String name, int type,
+            WorkSource newWs, int newPid, String newName,
+            String newHistoryName, int newType, boolean newUnimportantForLogging) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteChangeWakelockFromSourceLocked(ws, pid, name, type,
+                    newWs, newPid, newName, newHistoryName, newType, newUnimportantForLogging);
+        }
+    }
+
     public void noteStopWakelockFromSource(WorkSource ws, int pid, String name, int type) {
         enforceCallingPermission();
         synchronized (mStats) {
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index e1ccf46..df06bae 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -158,6 +158,39 @@
     }
 
     /**
+     * Called when a wake lock is changing.
+     */
+    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) {
+
+        final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
+        final int newMonitorType = getBatteryStatsWakeLockMonitorType(newFlags);
+        boolean unimportantForLogging = (flags&PowerManager.UNIMPORTANT_FOR_LOGGING) != 0
+                && ownerUid == Process.SYSTEM_UID;
+        if (workSource != null && newWorkSource != null) {
+            if (DEBUG) {
+                Slog.d(TAG, "onWakeLockChanging: flags=" + newFlags + ", tag=\"" + newTag
+                        + "\", packageName=" + newPackageName
+                        + ", ownerUid=" + newOwnerUid + ", ownerPid=" + newOwnerPid
+                        + ", workSource=" + newWorkSource);
+            }
+            try {
+                mBatteryStats.noteChangeWakelockFromSource(workSource, ownerPid, tag, monitorType,
+                        newWorkSource, newOwnerPid, newTag, newHistoryTag,
+                        newMonitorType, unimportantForLogging);
+            } catch (RemoteException ex) {
+                // Ignore
+            }
+        } else {
+            onWakeLockReleased(flags, tag, packageName, ownerUid, ownerPid, workSource);
+            onWakeLockAcquired(newFlags, newTag, newPackageName, newOwnerUid, newOwnerPid,
+                    newWorkSource, newHistoryTag);
+        }
+    }
+
+    /**
      * Called when a wake lock is released.
      */
     public void onWakeLockReleased(int flags, String tag, String packageName,
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index e7bbf1c..40ebe8d 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -646,9 +646,9 @@
                 wakeLock = mWakeLocks.get(index);
                 if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
                     // Update existing wake lock.  This shouldn't happen but is harmless.
-                    notifyWakeLockReleasedLocked(wakeLock);
+                    notifyWakeLockChangingLocked(wakeLock, flags, tag, packageName,
+                            uid, pid, ws, historyTag);
                     wakeLock.updateProperties(flags, tag, packageName, ws, historyTag, uid, pid);
-                    notifyWakeLockAcquiredLocked(wakeLock);
                 }
             } else {
                 wakeLock = new WakeLock(lock, flags, tag, packageName, ws, historyTag, uid, pid);
@@ -765,9 +765,10 @@
             }
 
             if (!wakeLock.hasSameWorkSource(ws)) {
-                notifyWakeLockReleasedLocked(wakeLock);
+                notifyWakeLockChangingLocked(wakeLock, wakeLock.mFlags, wakeLock.mTag,
+                        wakeLock.mPackageName, wakeLock.mOwnerUid, wakeLock.mOwnerPid,
+                        ws, wakeLock.mHistoryTag);
                 wakeLock.updateWorkSource(ws);
-                notifyWakeLockAcquiredLocked(wakeLock);
             }
         }
     }
@@ -791,6 +792,15 @@
         }
     }
 
+    private void notifyWakeLockChangingLocked(WakeLock wakeLock, int flags, String tag,
+            String packageName, int uid, int pid, WorkSource ws, String historyTag) {
+        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);
+        }
+    }
+
     private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
         if (mSystemReady && wakeLock.mNotifiedAcquired) {
             wakeLock.mNotifiedAcquired = false;