WakeLocks.java
/*
* Copyright 2018 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 androidx.work.impl.utils;
import static android.os.PowerManager.PARTIAL_WAKE_LOCK;
import android.content.Context;
import android.os.PowerManager;
import androidx.annotation.NonNull;
import androidx.annotation.RestrictTo;
import androidx.work.Logger;
import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;
/**
* A common class for creating WakeLocks.
*
* @hide
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public class WakeLocks {
private static final String TAG = Logger.tagWithPrefix("WakeLocks");
private static final WeakHashMap<PowerManager.WakeLock, String> sWakeLocks =
new WeakHashMap<>();
/**
* Creates and returns a new WakeLock.
*
* @param context The context from which to get the PowerManager
* @param tag A descriptive tag for the WakeLock; this method will prefix "WorkManager: "
* to it
* @return A new {@link android.os.PowerManager.WakeLock}
*/
public static PowerManager.WakeLock newWakeLock(
@NonNull Context context,
@NonNull String tag) {
PowerManager powerManager = (PowerManager) context.getApplicationContext()
.getSystemService(Context.POWER_SERVICE);
String tagWithPrefix = "WorkManager: " + tag;
PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PARTIAL_WAKE_LOCK, tagWithPrefix);
// Wakelocks are created on the command processor thread, but we check if they are still
// being held on the main thread.
synchronized (sWakeLocks) {
sWakeLocks.put(wakeLock, tagWithPrefix);
}
return wakeLock;
}
/**
* Checks to see if there are any {@link PowerManager.WakeLock}s that
* {@link androidx.work.impl.background.systemalarm.SystemAlarmService} holds when all the
* pending commands have been drained in the command queue.
*/
public static void checkWakeLocks() {
// There is a small chance that while we are checking if all the commands in the queue are
// drained and wake locks are no longer being held, a new command comes along and we end up
// with a ConcurrentModificationException. The addition of commands happens on the command
// processor thread and this check is done on the main thread.
Map<PowerManager.WakeLock, String> wakeLocksCopy = new HashMap<>();
synchronized (sWakeLocks) {
// Copy the WakeLocks - otherwise we can get a ConcurrentModificationException if the
// garbage collector kicks in and ends up removing something from the master copy while
// we are iterating over it.
wakeLocksCopy.putAll(sWakeLocks);
}
for (PowerManager.WakeLock wakeLock : wakeLocksCopy.keySet()) {
if (wakeLock != null && wakeLock.isHeld()) {
String message = String.format("WakeLock held for %s", wakeLocksCopy.get(wakeLock));
Logger.get().warning(TAG, message);
}
}
}
private WakeLocks() {
}
}