break up LocationManagerService's WakeLock

This commit splits LocationManagerService's monolithic WakeLock into
per-LocationManagerService.Receiver WakeLocks, for better WorkSource
accounting. This should make it easier to debug location-related
power issues.

Change-Id: I0d2897c305a38099f9663dc1bc9354ce4bbe1077
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index 016a664..0bf3a11 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -135,8 +135,8 @@
     // --- fields below are final after systemReady() ---
     private LocationFudger mLocationFudger;
     private GeofenceManager mGeofenceManager;
-    private PowerManager.WakeLock mWakeLock;
     private PackageManager mPackageManager;
+    private PowerManager mPowerManager;
     private GeocoderProxy mGeocodeProvider;
     private IGpsStatusProvider mGpsStatusProvider;
     private INetInitiatedListener mNetInitiatedListener;
@@ -144,9 +144,6 @@
     private PassiveProvider mPassiveProvider;  // track passive provider for special cases
     private LocationBlacklist mBlacklist;
 
-    // --- fields below are protected by mWakeLock ---
-    private int mPendingBroadcasts;
-
     // --- fields below are protected by mLock ---
     // Set of providers that are explicitly enabled
     private final Set<String> mEnabledProviders = new HashSet<String>();
@@ -209,10 +206,8 @@
             // fetch package manager
             mPackageManager = mContext.getPackageManager();
 
-            // prepare wake lock
-            PowerManager powerManager =
-                    (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-            mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+            // fetch power manager
+            mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
 
             // prepare worker thread
             mLocationHandler = new LocationWorkerHandler(BackgroundThread.get().getLooper());
@@ -466,6 +461,7 @@
         final HashMap<String,UpdateRecord> mUpdateRecords = new HashMap<String,UpdateRecord>();
 
         int mPendingBroadcasts;
+        PowerManager.WakeLock mWakeLock;
 
         Receiver(ILocationListener listener, PendingIntent intent, int pid, int uid,
                 String packageName) {
@@ -480,6 +476,10 @@
             mUid = uid;
             mPid = pid;
             mPackageName = packageName;
+
+            // construct/configure wakelock
+            mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKELOCK_KEY);
+            mWakeLock.setWorkSource(new WorkSource(mUid, mPackageName));
         }
 
         @Override
@@ -642,10 +642,7 @@
                 removeUpdatesLocked(this);
             }
             synchronized (this) {
-                if (mPendingBroadcasts > 0) {
-                    LocationManagerService.this.decrementPendingBroadcasts();
-                    mPendingBroadcasts = 0;
-                }
+                clearPendingBroadcastsLocked();
             }
         }
 
@@ -661,13 +658,24 @@
         // containing the sending of the broadcaset
         private void incrementPendingBroadcastsLocked() {
             if (mPendingBroadcasts++ == 0) {
-                LocationManagerService.this.incrementPendingBroadcasts();
+                mWakeLock.acquire();
             }
         }
 
         private void decrementPendingBroadcastsLocked() {
             if (--mPendingBroadcasts == 0) {
-                LocationManagerService.this.decrementPendingBroadcasts();
+                if (mWakeLock.isHeld()) {
+                    mWakeLock.release();
+                }
+            }
+        }
+
+        public void clearPendingBroadcastsLocked() {
+            if (mPendingBroadcasts > 0) {
+                mPendingBroadcasts = 0;
+                if (mWakeLock.isHeld()) {
+                    mWakeLock.release();
+                }
             }
         }
     }
@@ -1349,10 +1357,7 @@
         if (mReceivers.remove(receiver.mKey) != null && receiver.isListener()) {
             receiver.getListener().asBinder().unlinkToDeath(receiver, 0);
             synchronized (receiver) {
-                if (receiver.mPendingBroadcasts > 0) {
-                    decrementPendingBroadcasts();
-                    receiver.mPendingBroadcasts = 0;
-                }
+                receiver.clearPendingBroadcastsLocked();
             }
         }
 
@@ -1954,43 +1959,6 @@
         }
     };
 
-    // Wake locks
-
-    private void incrementPendingBroadcasts() {
-        synchronized (mWakeLock) {
-            if (mPendingBroadcasts++ == 0) {
-                try {
-                    mWakeLock.acquire();
-                    log("Acquired wakelock");
-                } catch (Exception e) {
-                    // This is to catch a runtime exception thrown when we try to release an
-                    // already released lock.
-                    Slog.e(TAG, "exception in acquireWakeLock()", e);
-                }
-            }
-        }
-    }
-
-    private void decrementPendingBroadcasts() {
-        synchronized (mWakeLock) {
-            if (--mPendingBroadcasts == 0) {
-                try {
-                    // Release wake lock
-                    if (mWakeLock.isHeld()) {
-                        mWakeLock.release();
-                        log("Released wakelock");
-                    } else {
-                        log("Can't release wakelock again!");
-                    }
-                } catch (Exception e) {
-                    // This is to catch a runtime exception thrown when we try to release an
-                    // already released lock.
-                    Slog.e(TAG, "exception in releaseWakeLock()", e);
-                }
-            }
-        }
-    }
-
     // Geocoder
 
     @Override