266 lines
11 KiB
Java
266 lines
11 KiB
Java
package androidx.work.impl.background.systemalarm;
|
|
|
|
import android.content.Context;
|
|
import android.content.Intent;
|
|
import android.os.Handler;
|
|
import android.os.Looper;
|
|
import android.os.PowerManager;
|
|
import android.text.TextUtils;
|
|
import androidx.annotation.MainThread;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RestrictTo;
|
|
import androidx.annotation.VisibleForTesting;
|
|
import androidx.work.Logger;
|
|
import androidx.work.impl.ExecutionListener;
|
|
import androidx.work.impl.Processor;
|
|
import androidx.work.impl.WorkManagerImpl;
|
|
import androidx.work.impl.utils.SerialExecutor;
|
|
import androidx.work.impl.utils.WakeLocks;
|
|
import androidx.work.impl.utils.WorkTimer;
|
|
import androidx.work.impl.utils.taskexecutor.TaskExecutor;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public class SystemAlarmDispatcher implements ExecutionListener {
|
|
private static final int DEFAULT_START_ID = 0;
|
|
private static final String KEY_START_ID = "KEY_START_ID";
|
|
private static final String PROCESS_COMMAND_TAG = "ProcessCommand";
|
|
public static final String TAG = Logger.tagWithPrefix("SystemAlarmDispatcher");
|
|
public final CommandHandler mCommandHandler;
|
|
@Nullable
|
|
private CommandsCompletedListener mCompletedListener;
|
|
public final Context mContext;
|
|
public Intent mCurrentIntent;
|
|
public final List<Intent> mIntents;
|
|
private final Handler mMainHandler;
|
|
private final Processor mProcessor;
|
|
private final TaskExecutor mTaskExecutor;
|
|
private final WorkManagerImpl mWorkManager;
|
|
private final WorkTimer mWorkTimer;
|
|
|
|
/* renamed from: androidx.work.impl.background.systemalarm.SystemAlarmDispatcher$1 reason: invalid class name */
|
|
public class AnonymousClass1 implements Runnable {
|
|
public AnonymousClass1() {
|
|
}
|
|
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
DequeueAndCheckForCompletion dequeueAndCheckForCompletion;
|
|
SystemAlarmDispatcher systemAlarmDispatcher;
|
|
synchronized (SystemAlarmDispatcher.this.mIntents) {
|
|
SystemAlarmDispatcher systemAlarmDispatcher2 = SystemAlarmDispatcher.this;
|
|
systemAlarmDispatcher2.mCurrentIntent = systemAlarmDispatcher2.mIntents.get(0);
|
|
}
|
|
Intent intent = SystemAlarmDispatcher.this.mCurrentIntent;
|
|
if (intent != null) {
|
|
String action = intent.getAction();
|
|
int intExtra = SystemAlarmDispatcher.this.mCurrentIntent.getIntExtra(SystemAlarmDispatcher.KEY_START_ID, 0);
|
|
Logger logger = Logger.get();
|
|
String str = SystemAlarmDispatcher.TAG;
|
|
logger.debug(str, String.format("Processing command %s, %s", SystemAlarmDispatcher.this.mCurrentIntent, Integer.valueOf(intExtra)), new Throwable[0]);
|
|
PowerManager.WakeLock newWakeLock = WakeLocks.newWakeLock(SystemAlarmDispatcher.this.mContext, String.format("%s (%s)", action, Integer.valueOf(intExtra)));
|
|
try {
|
|
Logger.get().debug(str, String.format("Acquiring operation wake lock (%s) %s", action, newWakeLock), new Throwable[0]);
|
|
newWakeLock.acquire();
|
|
SystemAlarmDispatcher systemAlarmDispatcher3 = SystemAlarmDispatcher.this;
|
|
systemAlarmDispatcher3.mCommandHandler.onHandleIntent(systemAlarmDispatcher3.mCurrentIntent, intExtra, systemAlarmDispatcher3);
|
|
Logger.get().debug(str, String.format("Releasing operation wake lock (%s) %s", action, newWakeLock), new Throwable[0]);
|
|
newWakeLock.release();
|
|
systemAlarmDispatcher = SystemAlarmDispatcher.this;
|
|
dequeueAndCheckForCompletion = new DequeueAndCheckForCompletion(systemAlarmDispatcher);
|
|
} catch (Throwable th) {
|
|
Logger.get().debug(SystemAlarmDispatcher.TAG, String.format("Releasing operation wake lock (%s) %s", action, newWakeLock), new Throwable[0]);
|
|
newWakeLock.release();
|
|
SystemAlarmDispatcher systemAlarmDispatcher4 = SystemAlarmDispatcher.this;
|
|
systemAlarmDispatcher4.postOnMainThread(new DequeueAndCheckForCompletion(systemAlarmDispatcher4));
|
|
throw th;
|
|
}
|
|
systemAlarmDispatcher.postOnMainThread(dequeueAndCheckForCompletion);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static class AddRunnable implements Runnable {
|
|
private final SystemAlarmDispatcher mDispatcher;
|
|
private final Intent mIntent;
|
|
private final int mStartId;
|
|
|
|
public AddRunnable(@NonNull SystemAlarmDispatcher systemAlarmDispatcher, @NonNull Intent intent, int i) {
|
|
this.mDispatcher = systemAlarmDispatcher;
|
|
this.mIntent = intent;
|
|
this.mStartId = i;
|
|
}
|
|
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
this.mDispatcher.add(this.mIntent, this.mStartId);
|
|
}
|
|
}
|
|
|
|
public interface CommandsCompletedListener {
|
|
void onAllCommandsCompleted();
|
|
}
|
|
|
|
public static class DequeueAndCheckForCompletion implements Runnable {
|
|
private final SystemAlarmDispatcher mDispatcher;
|
|
|
|
public DequeueAndCheckForCompletion(@NonNull SystemAlarmDispatcher systemAlarmDispatcher) {
|
|
this.mDispatcher = systemAlarmDispatcher;
|
|
}
|
|
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
this.mDispatcher.dequeueAndCheckForCompletion();
|
|
}
|
|
}
|
|
|
|
public SystemAlarmDispatcher(@NonNull Context context) {
|
|
this(context, null, null);
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public SystemAlarmDispatcher(@NonNull Context context, @Nullable Processor processor, @Nullable WorkManagerImpl workManagerImpl) {
|
|
Context applicationContext = context.getApplicationContext();
|
|
this.mContext = applicationContext;
|
|
this.mCommandHandler = new CommandHandler(applicationContext);
|
|
this.mWorkTimer = new WorkTimer();
|
|
workManagerImpl = workManagerImpl == null ? WorkManagerImpl.getInstance(context) : workManagerImpl;
|
|
this.mWorkManager = workManagerImpl;
|
|
processor = processor == null ? workManagerImpl.getProcessor() : processor;
|
|
this.mProcessor = processor;
|
|
this.mTaskExecutor = workManagerImpl.getWorkTaskExecutor();
|
|
processor.addExecutionListener(this);
|
|
this.mIntents = new ArrayList();
|
|
this.mCurrentIntent = null;
|
|
this.mMainHandler = new Handler(Looper.getMainLooper());
|
|
}
|
|
|
|
private void assertMainThread() {
|
|
if (this.mMainHandler.getLooper().getThread() != Thread.currentThread()) {
|
|
throw new IllegalStateException("Needs to be invoked on the main thread.");
|
|
}
|
|
}
|
|
|
|
@MainThread
|
|
private boolean hasIntentWithAction(@NonNull String str) {
|
|
assertMainThread();
|
|
synchronized (this.mIntents) {
|
|
for (Intent intent : this.mIntents) {
|
|
if (str.equals(intent.getAction())) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
@MainThread
|
|
private void processCommand() {
|
|
assertMainThread();
|
|
PowerManager.WakeLock newWakeLock = WakeLocks.newWakeLock(this.mContext, PROCESS_COMMAND_TAG);
|
|
try {
|
|
newWakeLock.acquire();
|
|
this.mWorkManager.getWorkTaskExecutor().executeOnBackgroundThread(new AnonymousClass1());
|
|
} finally {
|
|
newWakeLock.release();
|
|
}
|
|
}
|
|
|
|
@MainThread
|
|
public boolean add(@NonNull Intent intent, int i) {
|
|
Logger logger = Logger.get();
|
|
String str = TAG;
|
|
boolean z2 = false;
|
|
logger.debug(str, String.format("Adding command %s (%s)", intent, Integer.valueOf(i)), new Throwable[0]);
|
|
assertMainThread();
|
|
String action = intent.getAction();
|
|
if (TextUtils.isEmpty(action)) {
|
|
Logger.get().warning(str, "Unknown command. Ignoring", new Throwable[0]);
|
|
return false;
|
|
} else if (CommandHandler.ACTION_CONSTRAINTS_CHANGED.equals(action) && hasIntentWithAction(CommandHandler.ACTION_CONSTRAINTS_CHANGED)) {
|
|
return false;
|
|
} else {
|
|
intent.putExtra(KEY_START_ID, i);
|
|
synchronized (this.mIntents) {
|
|
if (!this.mIntents.isEmpty()) {
|
|
z2 = true;
|
|
}
|
|
this.mIntents.add(intent);
|
|
if (!z2) {
|
|
processCommand();
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
@MainThread
|
|
public void dequeueAndCheckForCompletion() {
|
|
Logger logger = Logger.get();
|
|
String str = TAG;
|
|
logger.debug(str, "Checking if commands are complete.", new Throwable[0]);
|
|
assertMainThread();
|
|
synchronized (this.mIntents) {
|
|
if (this.mCurrentIntent != null) {
|
|
Logger.get().debug(str, String.format("Removing command %s", this.mCurrentIntent), new Throwable[0]);
|
|
if (this.mIntents.remove(0).equals(this.mCurrentIntent)) {
|
|
this.mCurrentIntent = null;
|
|
} else {
|
|
throw new IllegalStateException("Dequeue-d command is not the first.");
|
|
}
|
|
}
|
|
SerialExecutor backgroundExecutor = this.mTaskExecutor.getBackgroundExecutor();
|
|
if (!this.mCommandHandler.hasPendingCommands() && this.mIntents.isEmpty() && !backgroundExecutor.hasPendingTasks()) {
|
|
Logger.get().debug(str, "No more commands & intents.", new Throwable[0]);
|
|
CommandsCompletedListener commandsCompletedListener = this.mCompletedListener;
|
|
if (commandsCompletedListener != null) {
|
|
commandsCompletedListener.onAllCommandsCompleted();
|
|
}
|
|
} else if (!this.mIntents.isEmpty()) {
|
|
processCommand();
|
|
}
|
|
}
|
|
}
|
|
|
|
public Processor getProcessor() {
|
|
return this.mProcessor;
|
|
}
|
|
|
|
public TaskExecutor getTaskExecutor() {
|
|
return this.mTaskExecutor;
|
|
}
|
|
|
|
public WorkManagerImpl getWorkManager() {
|
|
return this.mWorkManager;
|
|
}
|
|
|
|
public WorkTimer getWorkTimer() {
|
|
return this.mWorkTimer;
|
|
}
|
|
|
|
public void onDestroy() {
|
|
Logger.get().debug(TAG, "Destroying SystemAlarmDispatcher", new Throwable[0]);
|
|
this.mProcessor.removeExecutionListener(this);
|
|
this.mWorkTimer.onDestroy();
|
|
this.mCompletedListener = null;
|
|
}
|
|
|
|
@Override // androidx.work.impl.ExecutionListener
|
|
public void onExecuted(@NonNull String str, boolean z2) {
|
|
postOnMainThread(new AddRunnable(this, CommandHandler.createExecutionCompletedIntent(this.mContext, str, z2), 0));
|
|
}
|
|
|
|
public void postOnMainThread(@NonNull Runnable runnable) {
|
|
this.mMainHandler.post(runnable);
|
|
}
|
|
|
|
public void setCompletedListener(@NonNull CommandsCompletedListener commandsCompletedListener) {
|
|
if (this.mCompletedListener != null) {
|
|
Logger.get().error(TAG, "A completion listener for SystemAlarmDispatcher already exists.", new Throwable[0]);
|
|
} else {
|
|
this.mCompletedListener = commandsCompletedListener;
|
|
}
|
|
}
|
|
}
|