- Added realracing3-community.apk (71.57 MB) - Removed 32-bit support (armeabi-v7a) - Only includes arm64-v8a libraries - Decompiled source code included - Added README-community.md with analysis
251 lines
11 KiB
Java
251 lines
11 KiB
Java
package androidx.work.impl.background.systemjob;
|
|
|
|
import android.app.job.JobInfo;
|
|
import android.app.job.JobScheduler;
|
|
import android.content.ComponentName;
|
|
import android.content.Context;
|
|
import android.os.Build;
|
|
import android.os.PersistableBundle;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RequiresApi;
|
|
import androidx.annotation.RestrictTo;
|
|
import androidx.annotation.VisibleForTesting;
|
|
import androidx.core.util.Consumer;
|
|
import androidx.work.Configuration;
|
|
import androidx.work.Logger;
|
|
import androidx.work.OutOfQuotaPolicy;
|
|
import androidx.work.WorkInfo;
|
|
import androidx.work.impl.Scheduler;
|
|
import androidx.work.impl.WorkDatabase;
|
|
import androidx.work.impl.model.SystemIdInfo;
|
|
import androidx.work.impl.model.SystemIdInfoKt;
|
|
import androidx.work.impl.model.WorkGenerationalId;
|
|
import androidx.work.impl.model.WorkSpec;
|
|
import androidx.work.impl.model.WorkSpecDao;
|
|
import androidx.work.impl.model.WorkSpecKt;
|
|
import androidx.work.impl.utils.IdGenerator;
|
|
import java.util.ArrayList;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
|
|
@RequiresApi(23)
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
/* loaded from: classes.dex */
|
|
public class SystemJobScheduler implements Scheduler {
|
|
private static final String TAG = Logger.tagWithPrefix("SystemJobScheduler");
|
|
private final Configuration mConfiguration;
|
|
private final Context mContext;
|
|
private final JobScheduler mJobScheduler;
|
|
private final SystemJobInfoConverter mSystemJobInfoConverter;
|
|
private final WorkDatabase mWorkDatabase;
|
|
|
|
@Override // androidx.work.impl.Scheduler
|
|
public boolean hasLimitedSchedulingSlots() {
|
|
return true;
|
|
}
|
|
|
|
public SystemJobScheduler(@NonNull Context context, @NonNull WorkDatabase workDatabase, @NonNull Configuration configuration) {
|
|
this(context, workDatabase, configuration, JobSchedulerExtKt.getWmJobScheduler(context), new SystemJobInfoConverter(context, configuration.getClock(), configuration.isMarkingJobsAsImportantWhileForeground()));
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public SystemJobScheduler(@NonNull Context context, @NonNull WorkDatabase workDatabase, @NonNull Configuration configuration, @NonNull JobScheduler jobScheduler, @NonNull SystemJobInfoConverter systemJobInfoConverter) {
|
|
this.mContext = context;
|
|
this.mJobScheduler = jobScheduler;
|
|
this.mSystemJobInfoConverter = systemJobInfoConverter;
|
|
this.mWorkDatabase = workDatabase;
|
|
this.mConfiguration = configuration;
|
|
}
|
|
|
|
@Override // androidx.work.impl.Scheduler
|
|
public void schedule(@NonNull WorkSpec... workSpecArr) {
|
|
IdGenerator idGenerator = new IdGenerator(this.mWorkDatabase);
|
|
for (WorkSpec workSpec : workSpecArr) {
|
|
this.mWorkDatabase.beginTransaction();
|
|
try {
|
|
WorkSpec workSpec2 = this.mWorkDatabase.workSpecDao().getWorkSpec(workSpec.id);
|
|
if (workSpec2 == null) {
|
|
Logger.get().warning(TAG, "Skipping scheduling " + workSpec.id + " because it's no longer in the DB");
|
|
this.mWorkDatabase.setTransactionSuccessful();
|
|
} else if (workSpec2.state != WorkInfo.State.ENQUEUED) {
|
|
Logger.get().warning(TAG, "Skipping scheduling " + workSpec.id + " because it is no longer enqueued");
|
|
this.mWorkDatabase.setTransactionSuccessful();
|
|
} else {
|
|
WorkGenerationalId generationalId = WorkSpecKt.generationalId(workSpec);
|
|
SystemIdInfo systemIdInfo = this.mWorkDatabase.systemIdInfoDao().getSystemIdInfo(generationalId);
|
|
int nextJobSchedulerIdWithRange = systemIdInfo != null ? systemIdInfo.systemId : idGenerator.nextJobSchedulerIdWithRange(this.mConfiguration.getMinJobSchedulerId(), this.mConfiguration.getMaxJobSchedulerId());
|
|
if (systemIdInfo == null) {
|
|
this.mWorkDatabase.systemIdInfoDao().insertSystemIdInfo(SystemIdInfoKt.systemIdInfo(generationalId, nextJobSchedulerIdWithRange));
|
|
}
|
|
scheduleInternal(workSpec, nextJobSchedulerIdWithRange);
|
|
this.mWorkDatabase.setTransactionSuccessful();
|
|
}
|
|
} finally {
|
|
this.mWorkDatabase.endTransaction();
|
|
}
|
|
}
|
|
}
|
|
|
|
@VisibleForTesting
|
|
public void scheduleInternal(@NonNull WorkSpec workSpec, int i) {
|
|
JobInfo convert = this.mSystemJobInfoConverter.convert(workSpec, i);
|
|
Logger logger = Logger.get();
|
|
String str = TAG;
|
|
logger.debug(str, "Scheduling work ID " + workSpec.id + "Job ID " + i);
|
|
try {
|
|
if (this.mJobScheduler.schedule(convert) == 0) {
|
|
Logger.get().warning(str, "Unable to schedule work ID " + workSpec.id);
|
|
if (workSpec.expedited && workSpec.outOfQuotaPolicy == OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) {
|
|
workSpec.expedited = false;
|
|
Logger.get().debug(str, String.format("Scheduling a non-expedited job (work ID %s)", workSpec.id));
|
|
scheduleInternal(workSpec, i);
|
|
}
|
|
}
|
|
} catch (IllegalStateException e) {
|
|
String createErrorMessage = JobSchedulerExtKt.createErrorMessage(this.mContext, this.mWorkDatabase, this.mConfiguration);
|
|
Logger.get().error(TAG, createErrorMessage);
|
|
IllegalStateException illegalStateException = new IllegalStateException(createErrorMessage, e);
|
|
Consumer<Throwable> schedulingExceptionHandler = this.mConfiguration.getSchedulingExceptionHandler();
|
|
if (schedulingExceptionHandler != null) {
|
|
schedulingExceptionHandler.accept(illegalStateException);
|
|
return;
|
|
}
|
|
throw illegalStateException;
|
|
} catch (Throwable th) {
|
|
Logger.get().error(TAG, "Unable to schedule " + workSpec, th);
|
|
}
|
|
}
|
|
|
|
@Override // androidx.work.impl.Scheduler
|
|
public void cancel(@NonNull String str) {
|
|
List<Integer> pendingJobIds = getPendingJobIds(this.mContext, this.mJobScheduler, str);
|
|
if (pendingJobIds == null || pendingJobIds.isEmpty()) {
|
|
return;
|
|
}
|
|
Iterator<Integer> it = pendingJobIds.iterator();
|
|
while (it.hasNext()) {
|
|
cancelJobById(this.mJobScheduler, it.next().intValue());
|
|
}
|
|
this.mWorkDatabase.systemIdInfoDao().removeSystemIdInfo(str);
|
|
}
|
|
|
|
private static void cancelJobById(@NonNull JobScheduler jobScheduler, int i) {
|
|
try {
|
|
jobScheduler.cancel(i);
|
|
} catch (Throwable th) {
|
|
Logger.get().error(TAG, String.format(Locale.getDefault(), "Exception while trying to cancel job (%d)", Integer.valueOf(i)), th);
|
|
}
|
|
}
|
|
|
|
public static void cancelAllInAllNamespaces(@NonNull Context context) {
|
|
if (Build.VERSION.SDK_INT >= 34) {
|
|
JobSchedulerExtKt.getWmJobScheduler(context).cancelAll();
|
|
}
|
|
JobScheduler jobScheduler = (JobScheduler) context.getSystemService("jobscheduler");
|
|
List<JobInfo> pendingJobs = getPendingJobs(context, jobScheduler);
|
|
if (pendingJobs == null || pendingJobs.isEmpty()) {
|
|
return;
|
|
}
|
|
Iterator<JobInfo> it = pendingJobs.iterator();
|
|
while (it.hasNext()) {
|
|
cancelJobById(jobScheduler, it.next().getId());
|
|
}
|
|
}
|
|
|
|
public static boolean reconcileJobs(@NonNull Context context, @NonNull WorkDatabase workDatabase) {
|
|
JobScheduler wmJobScheduler = JobSchedulerExtKt.getWmJobScheduler(context);
|
|
List<JobInfo> pendingJobs = getPendingJobs(context, wmJobScheduler);
|
|
List<String> workSpecIds = workDatabase.systemIdInfoDao().getWorkSpecIds();
|
|
boolean z = false;
|
|
HashSet hashSet = new HashSet(pendingJobs != null ? pendingJobs.size() : 0);
|
|
if (pendingJobs != null && !pendingJobs.isEmpty()) {
|
|
for (JobInfo jobInfo : pendingJobs) {
|
|
WorkGenerationalId workGenerationalIdFromJobInfo = getWorkGenerationalIdFromJobInfo(jobInfo);
|
|
if (workGenerationalIdFromJobInfo != null) {
|
|
hashSet.add(workGenerationalIdFromJobInfo.getWorkSpecId());
|
|
} else {
|
|
cancelJobById(wmJobScheduler, jobInfo.getId());
|
|
}
|
|
}
|
|
}
|
|
Iterator<String> it = workSpecIds.iterator();
|
|
while (true) {
|
|
if (!it.hasNext()) {
|
|
break;
|
|
}
|
|
if (!hashSet.contains(it.next())) {
|
|
Logger.get().debug(TAG, "Reconciling jobs");
|
|
z = true;
|
|
break;
|
|
}
|
|
}
|
|
if (z) {
|
|
workDatabase.beginTransaction();
|
|
try {
|
|
WorkSpecDao workSpecDao = workDatabase.workSpecDao();
|
|
Iterator<String> it2 = workSpecIds.iterator();
|
|
while (it2.hasNext()) {
|
|
workSpecDao.markWorkSpecScheduled(it2.next(), -1L);
|
|
}
|
|
workDatabase.setTransactionSuccessful();
|
|
workDatabase.endTransaction();
|
|
} catch (Throwable th) {
|
|
workDatabase.endTransaction();
|
|
throw th;
|
|
}
|
|
}
|
|
return z;
|
|
}
|
|
|
|
@Nullable
|
|
public static List<JobInfo> getPendingJobs(@NonNull Context context, @NonNull JobScheduler jobScheduler) {
|
|
List<JobInfo> safePendingJobs = JobSchedulerExtKt.getSafePendingJobs(jobScheduler);
|
|
if (safePendingJobs == null) {
|
|
return null;
|
|
}
|
|
ArrayList arrayList = new ArrayList(safePendingJobs.size());
|
|
ComponentName componentName = new ComponentName(context, (Class<?>) SystemJobService.class);
|
|
for (JobInfo jobInfo : safePendingJobs) {
|
|
if (componentName.equals(jobInfo.getService())) {
|
|
arrayList.add(jobInfo);
|
|
}
|
|
}
|
|
return arrayList;
|
|
}
|
|
|
|
@Nullable
|
|
private static List<Integer> getPendingJobIds(@NonNull Context context, @NonNull JobScheduler jobScheduler, @NonNull String str) {
|
|
List<JobInfo> pendingJobs = getPendingJobs(context, jobScheduler);
|
|
if (pendingJobs == null) {
|
|
return null;
|
|
}
|
|
ArrayList arrayList = new ArrayList(2);
|
|
for (JobInfo jobInfo : pendingJobs) {
|
|
WorkGenerationalId workGenerationalIdFromJobInfo = getWorkGenerationalIdFromJobInfo(jobInfo);
|
|
if (workGenerationalIdFromJobInfo != null && str.equals(workGenerationalIdFromJobInfo.getWorkSpecId())) {
|
|
arrayList.add(Integer.valueOf(jobInfo.getId()));
|
|
}
|
|
}
|
|
return arrayList;
|
|
}
|
|
|
|
@Nullable
|
|
private static WorkGenerationalId getWorkGenerationalIdFromJobInfo(@NonNull JobInfo jobInfo) {
|
|
PersistableBundle extras = jobInfo.getExtras();
|
|
if (extras == null) {
|
|
return null;
|
|
}
|
|
try {
|
|
if (!extras.containsKey("EXTRA_WORK_SPEC_ID")) {
|
|
return null;
|
|
}
|
|
return new WorkGenerationalId(extras.getString("EXTRA_WORK_SPEC_ID"), extras.getInt("EXTRA_WORK_SPEC_GENERATION", 0));
|
|
} catch (NullPointerException unused) {
|
|
return null;
|
|
}
|
|
}
|
|
}
|