149 lines
7.5 KiB
Java
149 lines
7.5 KiB
Java
package androidx.work.impl.background.systemalarm;
|
|
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.PowerManager;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RestrictTo;
|
|
import androidx.annotation.WorkerThread;
|
|
import androidx.work.Logger;
|
|
import androidx.work.impl.ExecutionListener;
|
|
import androidx.work.impl.background.systemalarm.SystemAlarmDispatcher;
|
|
import androidx.work.impl.constraints.WorkConstraintsCallback;
|
|
import androidx.work.impl.constraints.WorkConstraintsTracker;
|
|
import androidx.work.impl.model.WorkSpec;
|
|
import androidx.work.impl.utils.WakeLocks;
|
|
import androidx.work.impl.utils.WorkTimer;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public class DelayMetCommandHandler implements WorkConstraintsCallback, ExecutionListener, WorkTimer.TimeLimitExceededListener {
|
|
private static final int STATE_INITIAL = 0;
|
|
private static final int STATE_START_REQUESTED = 1;
|
|
private static final int STATE_STOP_REQUESTED = 2;
|
|
private static final String TAG = Logger.tagWithPrefix("DelayMetCommandHandler");
|
|
private final Context mContext;
|
|
private int mCurrentState = 0;
|
|
private final SystemAlarmDispatcher mDispatcher;
|
|
private boolean mHasConstraints = false;
|
|
private final Object mLock = new Object();
|
|
private final int mStartId;
|
|
@Nullable
|
|
private PowerManager.WakeLock mWakeLock;
|
|
private final WorkConstraintsTracker mWorkConstraintsTracker;
|
|
private final String mWorkSpecId;
|
|
|
|
public DelayMetCommandHandler(@NonNull Context context, int i, @NonNull String str, @NonNull SystemAlarmDispatcher systemAlarmDispatcher) {
|
|
this.mContext = context;
|
|
this.mStartId = i;
|
|
this.mDispatcher = systemAlarmDispatcher;
|
|
this.mWorkSpecId = str;
|
|
this.mWorkConstraintsTracker = new WorkConstraintsTracker(context, systemAlarmDispatcher.getTaskExecutor(), this);
|
|
}
|
|
|
|
private void cleanUp() {
|
|
synchronized (this.mLock) {
|
|
this.mWorkConstraintsTracker.reset();
|
|
this.mDispatcher.getWorkTimer().stopTimer(this.mWorkSpecId);
|
|
PowerManager.WakeLock wakeLock = this.mWakeLock;
|
|
if (wakeLock != null && wakeLock.isHeld()) {
|
|
Logger.get().debug(TAG, String.format("Releasing wakelock %s for WorkSpec %s", this.mWakeLock, this.mWorkSpecId), new Throwable[0]);
|
|
this.mWakeLock.release();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void stopWork() {
|
|
synchronized (this.mLock) {
|
|
if (this.mCurrentState < 2) {
|
|
this.mCurrentState = 2;
|
|
Logger logger = Logger.get();
|
|
String str = TAG;
|
|
logger.debug(str, String.format("Stopping work for WorkSpec %s", this.mWorkSpecId), new Throwable[0]);
|
|
Intent createStopWorkIntent = CommandHandler.createStopWorkIntent(this.mContext, this.mWorkSpecId);
|
|
SystemAlarmDispatcher systemAlarmDispatcher = this.mDispatcher;
|
|
systemAlarmDispatcher.postOnMainThread(new SystemAlarmDispatcher.AddRunnable(systemAlarmDispatcher, createStopWorkIntent, this.mStartId));
|
|
if (this.mDispatcher.getProcessor().isEnqueued(this.mWorkSpecId)) {
|
|
Logger.get().debug(str, String.format("WorkSpec %s needs to be rescheduled", this.mWorkSpecId), new Throwable[0]);
|
|
Intent createScheduleWorkIntent = CommandHandler.createScheduleWorkIntent(this.mContext, this.mWorkSpecId);
|
|
SystemAlarmDispatcher systemAlarmDispatcher2 = this.mDispatcher;
|
|
systemAlarmDispatcher2.postOnMainThread(new SystemAlarmDispatcher.AddRunnable(systemAlarmDispatcher2, createScheduleWorkIntent, this.mStartId));
|
|
} else {
|
|
Logger.get().debug(str, String.format("Processor does not have WorkSpec %s. No need to reschedule ", this.mWorkSpecId), new Throwable[0]);
|
|
}
|
|
} else {
|
|
Logger.get().debug(TAG, String.format("Already stopped work for %s", this.mWorkSpecId), new Throwable[0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
@WorkerThread
|
|
public void handleProcessWork() {
|
|
this.mWakeLock = WakeLocks.newWakeLock(this.mContext, String.format("%s (%s)", this.mWorkSpecId, Integer.valueOf(this.mStartId)));
|
|
Logger logger = Logger.get();
|
|
String str = TAG;
|
|
logger.debug(str, String.format("Acquiring wakelock %s for WorkSpec %s", this.mWakeLock, this.mWorkSpecId), new Throwable[0]);
|
|
this.mWakeLock.acquire();
|
|
WorkSpec workSpec = this.mDispatcher.getWorkManager().getWorkDatabase().workSpecDao().getWorkSpec(this.mWorkSpecId);
|
|
if (workSpec == null) {
|
|
stopWork();
|
|
return;
|
|
}
|
|
boolean hasConstraints = workSpec.hasConstraints();
|
|
this.mHasConstraints = hasConstraints;
|
|
if (!hasConstraints) {
|
|
Logger.get().debug(str, String.format("No constraints for %s", this.mWorkSpecId), new Throwable[0]);
|
|
onAllConstraintsMet(Collections.singletonList(this.mWorkSpecId));
|
|
return;
|
|
}
|
|
this.mWorkConstraintsTracker.replace(Collections.singletonList(workSpec));
|
|
}
|
|
|
|
@Override // androidx.work.impl.constraints.WorkConstraintsCallback
|
|
public void onAllConstraintsMet(@NonNull List<String> list) {
|
|
if (list.contains(this.mWorkSpecId)) {
|
|
synchronized (this.mLock) {
|
|
if (this.mCurrentState == 0) {
|
|
this.mCurrentState = 1;
|
|
Logger.get().debug(TAG, String.format("onAllConstraintsMet for %s", this.mWorkSpecId), new Throwable[0]);
|
|
if (this.mDispatcher.getProcessor().startWork(this.mWorkSpecId)) {
|
|
this.mDispatcher.getWorkTimer().startTimer(this.mWorkSpecId, CommandHandler.WORK_PROCESSING_TIME_IN_MS, this);
|
|
} else {
|
|
cleanUp();
|
|
}
|
|
} else {
|
|
Logger.get().debug(TAG, String.format("Already started work for %s", this.mWorkSpecId), new Throwable[0]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override // androidx.work.impl.constraints.WorkConstraintsCallback
|
|
public void onAllConstraintsNotMet(@NonNull List<String> list) {
|
|
stopWork();
|
|
}
|
|
|
|
@Override // androidx.work.impl.ExecutionListener
|
|
public void onExecuted(@NonNull String str, boolean z2) {
|
|
Logger.get().debug(TAG, String.format("onExecuted %s, %s", str, Boolean.valueOf(z2)), new Throwable[0]);
|
|
cleanUp();
|
|
if (z2) {
|
|
Intent createScheduleWorkIntent = CommandHandler.createScheduleWorkIntent(this.mContext, this.mWorkSpecId);
|
|
SystemAlarmDispatcher systemAlarmDispatcher = this.mDispatcher;
|
|
systemAlarmDispatcher.postOnMainThread(new SystemAlarmDispatcher.AddRunnable(systemAlarmDispatcher, createScheduleWorkIntent, this.mStartId));
|
|
}
|
|
if (this.mHasConstraints) {
|
|
Intent createConstraintsChangedIntent = CommandHandler.createConstraintsChangedIntent(this.mContext);
|
|
SystemAlarmDispatcher systemAlarmDispatcher2 = this.mDispatcher;
|
|
systemAlarmDispatcher2.postOnMainThread(new SystemAlarmDispatcher.AddRunnable(systemAlarmDispatcher2, createConstraintsChangedIntent, this.mStartId));
|
|
}
|
|
}
|
|
|
|
@Override // androidx.work.impl.utils.WorkTimer.TimeLimitExceededListener
|
|
public void onTimeLimitExceeded(@NonNull String str) {
|
|
Logger.get().debug(TAG, String.format("Exceeded time limits on execution for %s", str), new Throwable[0]);
|
|
stopWork();
|
|
}
|
|
}
|