457 lines
20 KiB
Java
457 lines
20 KiB
Java
package androidx.work.impl;
|
|
|
|
import android.app.PendingIntent;
|
|
import android.content.BroadcastReceiver;
|
|
import android.content.Context;
|
|
import android.os.Build;
|
|
import androidx.annotation.NonNull;
|
|
import androidx.annotation.Nullable;
|
|
import androidx.annotation.RestrictTo;
|
|
import androidx.arch.core.util.Function;
|
|
import androidx.lifecycle.LiveData;
|
|
import androidx.work.Configuration;
|
|
import androidx.work.ExistingPeriodicWorkPolicy;
|
|
import androidx.work.ExistingWorkPolicy;
|
|
import androidx.work.Logger;
|
|
import androidx.work.OneTimeWorkRequest;
|
|
import androidx.work.Operation;
|
|
import androidx.work.PeriodicWorkRequest;
|
|
import androidx.work.R;
|
|
import androidx.work.WorkContinuation;
|
|
import androidx.work.WorkInfo;
|
|
import androidx.work.WorkManager;
|
|
import androidx.work.WorkQuery;
|
|
import androidx.work.WorkRequest;
|
|
import androidx.work.WorkerParameters;
|
|
import androidx.work.impl.background.greedy.GreedyScheduler;
|
|
import androidx.work.impl.background.systemjob.SystemJobScheduler;
|
|
import androidx.work.impl.foreground.SystemForegroundDispatcher;
|
|
import androidx.work.impl.model.WorkSpec;
|
|
import androidx.work.impl.utils.CancelWorkRunnable;
|
|
import androidx.work.impl.utils.ForceStopRunnable;
|
|
import androidx.work.impl.utils.LiveDataUtils;
|
|
import androidx.work.impl.utils.PreferenceUtils;
|
|
import androidx.work.impl.utils.PruneWorkRunnable;
|
|
import androidx.work.impl.utils.RawQueries;
|
|
import androidx.work.impl.utils.StartWorkRunnable;
|
|
import androidx.work.impl.utils.StatusRunnable;
|
|
import androidx.work.impl.utils.StopWorkRunnable;
|
|
import androidx.work.impl.utils.futures.SettableFuture;
|
|
import androidx.work.impl.utils.taskexecutor.TaskExecutor;
|
|
import androidx.work.impl.utils.taskexecutor.WorkManagerTaskExecutor;
|
|
import c.i.b.d.a.a;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.List;
|
|
import java.util.UUID;
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public class WorkManagerImpl extends WorkManager {
|
|
public static final int MAX_PRE_JOB_SCHEDULER_API_LEVEL = 22;
|
|
public static final int MIN_JOB_SCHEDULER_API_LEVEL = 23;
|
|
private static WorkManagerImpl sDefaultInstance;
|
|
private static WorkManagerImpl sDelegatedInstance;
|
|
private static final Object sLock = new Object();
|
|
private Configuration mConfiguration;
|
|
private Context mContext;
|
|
private boolean mForceStopRunnableCompleted;
|
|
private PreferenceUtils mPreferenceUtils;
|
|
private Processor mProcessor;
|
|
private BroadcastReceiver.PendingResult mRescheduleReceiverResult;
|
|
private List<Scheduler> mSchedulers;
|
|
private WorkDatabase mWorkDatabase;
|
|
private TaskExecutor mWorkTaskExecutor;
|
|
|
|
/* renamed from: androidx.work.impl.WorkManagerImpl$1 reason: invalid class name */
|
|
public class AnonymousClass1 implements Runnable {
|
|
public final /* synthetic */ SettableFuture val$future;
|
|
public final /* synthetic */ PreferenceUtils val$preferenceUtils;
|
|
|
|
public AnonymousClass1(SettableFuture settableFuture, PreferenceUtils preferenceUtils) {
|
|
this.val$future = settableFuture;
|
|
this.val$preferenceUtils = preferenceUtils;
|
|
}
|
|
|
|
@Override // java.lang.Runnable
|
|
public void run() {
|
|
try {
|
|
this.val$future.set(Long.valueOf(this.val$preferenceUtils.getLastCancelAllTimeMillis()));
|
|
} catch (Throwable th) {
|
|
this.val$future.setException(th);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* renamed from: androidx.work.impl.WorkManagerImpl$2 reason: invalid class name */
|
|
public class AnonymousClass2 implements Function<List<WorkSpec.WorkInfoPojo>, WorkInfo> {
|
|
public AnonymousClass2() {
|
|
}
|
|
|
|
public WorkInfo apply(List<WorkSpec.WorkInfoPojo> list) {
|
|
if (list == null || list.size() <= 0) {
|
|
return null;
|
|
}
|
|
return list.get(0).toWorkInfo();
|
|
}
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public WorkManagerImpl(@NonNull Context context, @NonNull Configuration configuration, @NonNull TaskExecutor taskExecutor) {
|
|
this(context, configuration, taskExecutor, context.getResources().getBoolean(R.bool.workmanager_test_configuration));
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public WorkManagerImpl(@NonNull Context context, @NonNull Configuration configuration, @NonNull TaskExecutor taskExecutor, @NonNull WorkDatabase workDatabase) {
|
|
Context applicationContext = context.getApplicationContext();
|
|
Logger.setLogger(new Logger.LogcatLogger(configuration.getMinimumLoggingLevel()));
|
|
List<Scheduler> createSchedulers = createSchedulers(applicationContext, configuration, taskExecutor);
|
|
internalInit(context, configuration, taskExecutor, workDatabase, createSchedulers, new Processor(context, configuration, taskExecutor, workDatabase, createSchedulers));
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public WorkManagerImpl(@NonNull Context context, @NonNull Configuration configuration, @NonNull TaskExecutor taskExecutor, @NonNull WorkDatabase workDatabase, @NonNull List<Scheduler> list, @NonNull Processor processor) {
|
|
internalInit(context, configuration, taskExecutor, workDatabase, list, processor);
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public WorkManagerImpl(@NonNull Context context, @NonNull Configuration configuration, @NonNull TaskExecutor taskExecutor, boolean z2) {
|
|
this(context, configuration, taskExecutor, WorkDatabase.create(context.getApplicationContext(), taskExecutor.getBackgroundExecutor(), z2));
|
|
}
|
|
|
|
private WorkContinuationImpl createWorkContinuationForUniquePeriodicWork(@NonNull String str, @NonNull ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy, @NonNull PeriodicWorkRequest periodicWorkRequest) {
|
|
return new WorkContinuationImpl(this, str, existingPeriodicWorkPolicy == ExistingPeriodicWorkPolicy.KEEP ? ExistingWorkPolicy.KEEP : ExistingWorkPolicy.REPLACE, Collections.singletonList(periodicWorkRequest));
|
|
}
|
|
|
|
@Nullable
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
@Deprecated
|
|
public static WorkManagerImpl getInstance() {
|
|
synchronized (sLock) {
|
|
WorkManagerImpl workManagerImpl = sDelegatedInstance;
|
|
if (workManagerImpl != null) {
|
|
return workManagerImpl;
|
|
}
|
|
return sDefaultInstance;
|
|
}
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public static WorkManagerImpl getInstance(@NonNull Context context) {
|
|
WorkManagerImpl instance;
|
|
synchronized (sLock) {
|
|
instance = getInstance();
|
|
if (instance == null) {
|
|
Context applicationContext = context.getApplicationContext();
|
|
if (applicationContext instanceof Configuration.Provider) {
|
|
initialize(applicationContext, ((Configuration.Provider) applicationContext).getWorkManagerConfiguration());
|
|
instance = getInstance(applicationContext);
|
|
} else {
|
|
throw new IllegalStateException("WorkManager is not initialized properly. You have explicitly disabled WorkManagerInitializer in your manifest, have not manually called WorkManager#initialize at this point, and your Application does not implement Configuration.Provider.");
|
|
}
|
|
}
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public static void initialize(@NonNull Context context, @NonNull Configuration configuration) {
|
|
synchronized (sLock) {
|
|
WorkManagerImpl workManagerImpl = sDelegatedInstance;
|
|
if (workManagerImpl != null) {
|
|
if (sDefaultInstance != null) {
|
|
throw new IllegalStateException("WorkManager is already initialized. Did you try to initialize it manually without disabling WorkManagerInitializer? See WorkManager#initialize(Context, Configuration) or the class level Javadoc for more information.");
|
|
}
|
|
}
|
|
if (workManagerImpl == null) {
|
|
Context applicationContext = context.getApplicationContext();
|
|
if (sDefaultInstance == null) {
|
|
sDefaultInstance = new WorkManagerImpl(applicationContext, configuration, new WorkManagerTaskExecutor(configuration.getTaskExecutor()));
|
|
}
|
|
sDelegatedInstance = sDefaultInstance;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void internalInit(@NonNull Context context, @NonNull Configuration configuration, @NonNull TaskExecutor taskExecutor, @NonNull WorkDatabase workDatabase, @NonNull List<Scheduler> list, @NonNull Processor processor) {
|
|
Context applicationContext = context.getApplicationContext();
|
|
this.mContext = applicationContext;
|
|
this.mConfiguration = configuration;
|
|
this.mWorkTaskExecutor = taskExecutor;
|
|
this.mWorkDatabase = workDatabase;
|
|
this.mSchedulers = list;
|
|
this.mProcessor = processor;
|
|
this.mPreferenceUtils = new PreferenceUtils(workDatabase);
|
|
this.mForceStopRunnableCompleted = false;
|
|
if (Build.VERSION.SDK_INT < 24 || !applicationContext.isDeviceProtectedStorage()) {
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(new ForceStopRunnable(applicationContext, this));
|
|
return;
|
|
}
|
|
throw new IllegalStateException("Cannot initialize WorkManager in direct boot mode");
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public static void setDelegate(@Nullable WorkManagerImpl workManagerImpl) {
|
|
synchronized (sLock) {
|
|
sDelegatedInstance = workManagerImpl;
|
|
}
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public WorkContinuation beginUniqueWork(@NonNull String str, @NonNull ExistingWorkPolicy existingWorkPolicy, @NonNull List<OneTimeWorkRequest> list) {
|
|
if (!list.isEmpty()) {
|
|
return new WorkContinuationImpl(this, str, existingWorkPolicy, list);
|
|
}
|
|
throw new IllegalArgumentException("beginUniqueWork needs at least one OneTimeWorkRequest.");
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public WorkContinuation beginWith(@NonNull List<OneTimeWorkRequest> list) {
|
|
if (!list.isEmpty()) {
|
|
return new WorkContinuationImpl(this, list);
|
|
}
|
|
throw new IllegalArgumentException("beginWith needs at least one OneTimeWorkRequest.");
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public Operation cancelAllWork() {
|
|
CancelWorkRunnable forAll = CancelWorkRunnable.forAll(this);
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(forAll);
|
|
return forAll.getOperation();
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public Operation cancelAllWorkByTag(@NonNull String str) {
|
|
CancelWorkRunnable forTag = CancelWorkRunnable.forTag(str, this);
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(forTag);
|
|
return forTag.getOperation();
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public Operation cancelUniqueWork(@NonNull String str) {
|
|
CancelWorkRunnable forName = CancelWorkRunnable.forName(str, this, true);
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(forName);
|
|
return forName.getOperation();
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public Operation cancelWorkById(@NonNull UUID uuid) {
|
|
CancelWorkRunnable forId = CancelWorkRunnable.forId(uuid, this);
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(forId);
|
|
return forId.getOperation();
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public PendingIntent createCancelPendingIntent(@NonNull UUID uuid) {
|
|
return PendingIntent.getService(this.mContext, 0, SystemForegroundDispatcher.createCancelWorkIntent(this.mContext, uuid.toString()), 134217728);
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public List<Scheduler> createSchedulers(@NonNull Context context, @NonNull Configuration configuration, @NonNull TaskExecutor taskExecutor) {
|
|
return Arrays.asList(Schedulers.createBestAvailableBackgroundScheduler(context, this), new GreedyScheduler(context, configuration, taskExecutor, this));
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public Operation enqueue(@NonNull List<? extends WorkRequest> list) {
|
|
if (!list.isEmpty()) {
|
|
return new WorkContinuationImpl(this, list).enqueue();
|
|
}
|
|
throw new IllegalArgumentException("enqueue needs at least one WorkRequest.");
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public Operation enqueueUniquePeriodicWork(@NonNull String str, @NonNull ExistingPeriodicWorkPolicy existingPeriodicWorkPolicy, @NonNull PeriodicWorkRequest periodicWorkRequest) {
|
|
return createWorkContinuationForUniquePeriodicWork(str, existingPeriodicWorkPolicy, periodicWorkRequest).enqueue();
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public Operation enqueueUniqueWork(@NonNull String str, @NonNull ExistingWorkPolicy existingWorkPolicy, @NonNull List<OneTimeWorkRequest> list) {
|
|
return new WorkContinuationImpl(this, str, existingWorkPolicy, list).enqueue();
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public Context getApplicationContext() {
|
|
return this.mContext;
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public Configuration getConfiguration() {
|
|
return this.mConfiguration;
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public a<Long> getLastCancelAllTimeMillis() {
|
|
SettableFuture create = SettableFuture.create();
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(new AnonymousClass1(create, this.mPreferenceUtils));
|
|
return create;
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public LiveData<Long> getLastCancelAllTimeMillisLiveData() {
|
|
return this.mPreferenceUtils.getLastCancelAllTimeMillisLiveData();
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public PreferenceUtils getPreferenceUtils() {
|
|
return this.mPreferenceUtils;
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public Processor getProcessor() {
|
|
return this.mProcessor;
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public List<Scheduler> getSchedulers() {
|
|
return this.mSchedulers;
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public WorkDatabase getWorkDatabase() {
|
|
return this.mWorkDatabase;
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public a<WorkInfo> getWorkInfoById(@NonNull UUID uuid) {
|
|
StatusRunnable<WorkInfo> forUUID = StatusRunnable.forUUID(this, uuid);
|
|
this.mWorkTaskExecutor.getBackgroundExecutor().execute(forUUID);
|
|
return forUUID.getFuture();
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public LiveData<WorkInfo> getWorkInfoByIdLiveData(@NonNull UUID uuid) {
|
|
return LiveDataUtils.dedupedMappedLiveDataFor(this.mWorkDatabase.workSpecDao().getWorkStatusPojoLiveDataForIds(Collections.singletonList(uuid.toString())), new AnonymousClass2(), this.mWorkTaskExecutor);
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public a<List<WorkInfo>> getWorkInfos(@NonNull WorkQuery workQuery) {
|
|
StatusRunnable<List<WorkInfo>> forWorkQuerySpec = StatusRunnable.forWorkQuerySpec(this, workQuery);
|
|
this.mWorkTaskExecutor.getBackgroundExecutor().execute(forWorkQuerySpec);
|
|
return forWorkQuerySpec.getFuture();
|
|
}
|
|
|
|
public LiveData<List<WorkInfo>> getWorkInfosById(@NonNull List<String> list) {
|
|
return LiveDataUtils.dedupedMappedLiveDataFor(this.mWorkDatabase.workSpecDao().getWorkStatusPojoLiveDataForIds(list), WorkSpec.WORK_INFO_MAPPER, this.mWorkTaskExecutor);
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public a<List<WorkInfo>> getWorkInfosByTag(@NonNull String str) {
|
|
StatusRunnable<List<WorkInfo>> forTag = StatusRunnable.forTag(this, str);
|
|
this.mWorkTaskExecutor.getBackgroundExecutor().execute(forTag);
|
|
return forTag.getFuture();
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public LiveData<List<WorkInfo>> getWorkInfosByTagLiveData(@NonNull String str) {
|
|
return LiveDataUtils.dedupedMappedLiveDataFor(this.mWorkDatabase.workSpecDao().getWorkStatusPojoLiveDataForTag(str), WorkSpec.WORK_INFO_MAPPER, this.mWorkTaskExecutor);
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public a<List<WorkInfo>> getWorkInfosForUniqueWork(@NonNull String str) {
|
|
StatusRunnable<List<WorkInfo>> forUniqueWork = StatusRunnable.forUniqueWork(this, str);
|
|
this.mWorkTaskExecutor.getBackgroundExecutor().execute(forUniqueWork);
|
|
return forUniqueWork.getFuture();
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public LiveData<List<WorkInfo>> getWorkInfosForUniqueWorkLiveData(@NonNull String str) {
|
|
return LiveDataUtils.dedupedMappedLiveDataFor(this.mWorkDatabase.workSpecDao().getWorkStatusPojoLiveDataForName(str), WorkSpec.WORK_INFO_MAPPER, this.mWorkTaskExecutor);
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public LiveData<List<WorkInfo>> getWorkInfosLiveData(@NonNull WorkQuery workQuery) {
|
|
return LiveDataUtils.dedupedMappedLiveDataFor(this.mWorkDatabase.rawWorkInfoDao().getWorkInfoPojosLiveData(RawQueries.workQueryToRawQuery(workQuery)), WorkSpec.WORK_INFO_MAPPER, this.mWorkTaskExecutor);
|
|
}
|
|
|
|
@NonNull
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public TaskExecutor getWorkTaskExecutor() {
|
|
return this.mWorkTaskExecutor;
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public void onForceStopRunnableCompleted() {
|
|
synchronized (sLock) {
|
|
this.mForceStopRunnableCompleted = true;
|
|
BroadcastReceiver.PendingResult pendingResult = this.mRescheduleReceiverResult;
|
|
if (pendingResult != null) {
|
|
pendingResult.finish();
|
|
this.mRescheduleReceiverResult = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override // androidx.work.WorkManager
|
|
@NonNull
|
|
public Operation pruneWork() {
|
|
PruneWorkRunnable pruneWorkRunnable = new PruneWorkRunnable(this);
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(pruneWorkRunnable);
|
|
return pruneWorkRunnable.getOperation();
|
|
}
|
|
|
|
public void rescheduleEligibleWork() {
|
|
if (Build.VERSION.SDK_INT >= 23) {
|
|
SystemJobScheduler.cancelAll(getApplicationContext());
|
|
}
|
|
getWorkDatabase().workSpecDao().resetScheduledState();
|
|
Schedulers.schedule(getConfiguration(), getWorkDatabase(), getSchedulers());
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public void setReschedulePendingResult(@NonNull BroadcastReceiver.PendingResult pendingResult) {
|
|
synchronized (sLock) {
|
|
this.mRescheduleReceiverResult = pendingResult;
|
|
if (this.mForceStopRunnableCompleted) {
|
|
pendingResult.finish();
|
|
this.mRescheduleReceiverResult = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public void startWork(@NonNull String str) {
|
|
startWork(str, null);
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public void startWork(@NonNull String str, @Nullable WorkerParameters.RuntimeExtras runtimeExtras) {
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(new StartWorkRunnable(this, str, runtimeExtras));
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public void stopForegroundWork(@NonNull String str) {
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(new StopWorkRunnable(this, str, true));
|
|
}
|
|
|
|
@RestrictTo({RestrictTo.Scope.LIBRARY_GROUP})
|
|
public void stopWork(@NonNull String str) {
|
|
this.mWorkTaskExecutor.executeOnBackgroundThread(new StopWorkRunnable(this, str, false));
|
|
}
|
|
}
|