Dialer: Replace AsyncTask(Loader)s
They are deprecated
Change-Id: Ie927304e66edab39465850954fc380e8c0c4cfed
diff --git a/java/com/android/contacts/common/dialog/ClearFrequentsDialog.java b/java/com/android/contacts/common/dialog/ClearFrequentsDialog.java
index c320341..ecea6ce 100644
--- a/java/com/android/contacts/common/dialog/ClearFrequentsDialog.java
+++ b/java/com/android/contacts/common/dialog/ClearFrequentsDialog.java
@@ -21,19 +21,22 @@
import android.app.ProgressDialog;
import android.content.ContentResolver;
import android.content.Context;
-import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
-import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.provider.ContactsContract;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.DialogFragment;
import androidx.fragment.app.FragmentManager;
-import com.android.dialer.contacts.resources.R;
+import com.android.dialer.R;
import com.android.dialer.util.PermissionsUtil;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
/** Dialog that clears the frequently contacted list after confirming with the user. */
public class ClearFrequentsDialog extends DialogFragment {
@@ -47,39 +50,27 @@
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Context context = getActivity().getApplicationContext();
final ContentResolver resolver = getActivity().getContentResolver();
- final OnClickListener okListener =
- new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (!PermissionsUtil.hasContactsReadPermissions(context)) {
- return;
- }
+ final OnClickListener okListener = (dialog, which) -> {
+ if (!PermissionsUtil.hasContactsReadPermissions(context)) {
+ return;
+ }
- final ProgressDialog progressDialog =
- ProgressDialog.show(
- getContext(),
- getString(R.string.clearFrequentsProgress_title),
- null,
- true,
- true);
+ final ProgressDialog progressDialog =
+ ProgressDialog.show(
+ getContext(),
+ getString(R.string.clearFrequentsProgress_title),
+ null,
+ true,
+ true);
- final AsyncTask<Void, Void, Void> task =
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- resolver.delete(
- ContactsContract.DataUsageFeedback.DELETE_USAGE_URI, null, null);
- return null;
- }
+ final ExecutorService executorService = Executors.newSingleThreadExecutor();
+ final Handler handler = new Handler(Looper.getMainLooper());
- @Override
- protected void onPostExecute(Void result) {
- progressDialog.dismiss();
- }
- };
- task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
- }
- };
+ executorService.execute(() -> {
+ resolver.delete(ContactsContract.DataUsageFeedback.DELETE_USAGE_URI, null, null);
+ handler.post(progressDialog::dismiss);
+ });
+ };
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.clearFrequentsConfirmation_title)
.setMessage(R.string.clearFrequentsConfirmation)
diff --git a/java/com/android/contacts/common/model/AccountTypeManager.java b/java/com/android/contacts/common/model/AccountTypeManager.java
index 70800ae..ee23534 100644
--- a/java/com/android/contacts/common/model/AccountTypeManager.java
+++ b/java/com/android/contacts/common/model/AccountTypeManager.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2009 The Android Open Source Project
+ * Copyright (C) 2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -30,7 +31,6 @@
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
@@ -63,6 +63,8 @@
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -775,18 +777,20 @@
* the list of all potential invitable account types. Once the work is completed, the list of
* account types is stored in the {@link AccountTypeManager}'s {@link InvitableAccountTypeCache}.
*/
- private class FindInvitablesTask
- extends AsyncTask<Void, Void, Map<AccountTypeWithDataSet, AccountType>> {
+ private class FindInvitablesTask {
- @Override
- protected Map<AccountTypeWithDataSet, AccountType> doInBackground(Void... params) {
- return findUsableInvitableAccountTypes(mContext);
- }
+ private void execute() {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Handler handler = new Handler(Looper.getMainLooper());
- @Override
- protected void onPostExecute(Map<AccountTypeWithDataSet, AccountType> accountTypes) {
- mInvitableAccountTypeCache.setCachedValue(accountTypes);
- mInvitablesTaskIsRunning.set(false);
+ executor.execute(() -> {
+ final Map<AccountTypeWithDataSet, AccountType> accountTypes =
+ findUsableInvitableAccountTypes(mContext);
+ handler.post(() -> {
+ mInvitableAccountTypeCache.setCachedValue(accountTypes);
+ mInvitablesTaskIsRunning.set(false);
+ });
+ });
}
}
}
diff --git a/java/com/android/contacts/common/model/ContactLoader.java b/java/com/android/contacts/common/model/ContactLoader.java
index a3a3b9d..b644ccf 100644
--- a/java/com/android/contacts/common/model/ContactLoader.java
+++ b/java/com/android/contacts/common/model/ContactLoader.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,7 +17,6 @@
package com.android.contacts.common.model;
-import android.content.AsyncTaskLoader;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
@@ -36,6 +36,9 @@
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
+
+import androidx.loader.content.AsyncTaskLoader;
+
import com.android.contacts.common.GroupMetaData;
import com.android.contacts.common.model.account.AccountType;
import com.android.contacts.common.model.account.AccountTypeWithDataSet;
@@ -53,6 +56,7 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
@@ -64,6 +68,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Set;
+
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
diff --git a/java/com/android/dialer/app/calllog/CallLogAdapter.java b/java/com/android/dialer/app/calllog/CallLogAdapter.java
index 53523bd..09f3b96 100644
--- a/java/com/android/dialer/app/calllog/CallLogAdapter.java
+++ b/java/com/android/dialer/app/calllog/CallLogAdapter.java
@@ -24,8 +24,9 @@
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.os.Trace;
import android.provider.BlockedNumberContract;
import android.provider.CallLog;
@@ -85,6 +86,8 @@
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/** Adapter class to fill in data for the Call Log. */
public class CallLogAdapter extends GroupingListAdapter
@@ -121,7 +124,6 @@
/** Helper to group call log entries. */
private final CallLogGroupBuilder callLogGroupBuilder;
- private final AsyncTaskExecutor asyncTaskExecutor = AsyncTaskExecutors.createAsyncTaskExecutor();
private ContactInfoCache contactInfoCache;
// Tracks the position of the currently expanded list item.
private int currentlyExpandedPosition = RecyclerView.NO_POSITION;
@@ -665,7 +667,7 @@
updateCheckMarkedStatusOfEntry(views);
if (views.asyncTask != null) {
- views.asyncTask.cancel(true);
+ views.asyncTask.cancel();
}
}
}
@@ -746,38 +748,68 @@
viewHolder.isBlocked = false;
viewHolder.setDetailedPhoneDetails(callDetailsEntries);
- final AsyncTask<Void, Void, Boolean> loadDataTask =
- new AsyncTask<Void, Void, Boolean>() {
- @Override
- protected Boolean doInBackground(Void... params) {
- viewHolder.isBlocked = BlockedNumberContract.canCurrentUserBlockNumbers(activity) &&
- BlockedNumberContract.isBlocked(activity, viewHolder.number);
- details.isBlocked = viewHolder.isBlocked;
- if (isCancelled()) {
- return false;
- }
- return !isCancelled() && loadData(viewHolder, rowId, details);
- }
-
- @Override
- protected void onPostExecute(Boolean success) {
- viewHolder.isLoaded = true;
- if (success) {
- viewHolder.callbackAction = getCallbackAction(viewHolder.rowId);
- int currentDayGroup = getDayGroup(viewHolder.rowId);
- if (currentDayGroup != details.previousGroup) {
- viewHolder.dayGroupHeaderVisibility = View.VISIBLE;
- viewHolder.dayGroupHeaderText = getGroupDescription(currentDayGroup);
- } else {
- viewHolder.dayGroupHeaderVisibility = View.GONE;
- }
- render(viewHolder, details, rowId);
- }
- }
- };
+ final LoadDataTask loadDataTask = new LoadDataTask(viewHolder, details, rowId);
viewHolder.asyncTask = loadDataTask;
- asyncTaskExecutor.submit(LOAD_DATA_TASK_IDENTIFIER, loadDataTask);
+ loadDataTask.execute();
+ }
+
+ public interface LoadDataTaskInterface {
+ void execute();
+ void cancel();
+ }
+
+ private class LoadDataTask implements LoadDataTaskInterface {
+
+ private boolean mIsCancelled = false;
+ private final CallLogListItemViewHolder mViewHolder;
+ private final PhoneCallDetails mDetails;
+ private final long mRowId;
+
+ private final ExecutorService mExecutor;
+ private final Handler mHandler;
+
+ public LoadDataTask(CallLogListItemViewHolder viewHolder, PhoneCallDetails details,
+ long rowId) {
+ mExecutor = Executors.newSingleThreadExecutor();
+ mHandler = new Handler(Looper.getMainLooper());
+ mViewHolder = viewHolder;
+ mDetails = details;
+ mRowId = rowId;
+ }
+
+ public void execute() {
+ mExecutor.execute(() -> {
+ final boolean success;
+ mViewHolder.isBlocked = BlockedNumberContract.canCurrentUserBlockNumbers(activity) &&
+ BlockedNumberContract.isBlocked(activity, mViewHolder.number);
+ mDetails.isBlocked = mViewHolder.isBlocked;
+ if (mIsCancelled) {
+ success = false;
+ } else {
+ success = !mIsCancelled && loadData(mViewHolder, mRowId, mDetails);
+ }
+
+ mHandler.post(() -> {
+ mViewHolder.isLoaded = true;
+ if (success) {
+ mViewHolder.callbackAction = getCallbackAction(mViewHolder.rowId);
+ int currentDayGroup = getDayGroup(mViewHolder.rowId);
+ if (currentDayGroup != mDetails.previousGroup) {
+ mViewHolder.dayGroupHeaderVisibility = View.VISIBLE;
+ mViewHolder.dayGroupHeaderText = getGroupDescription(currentDayGroup);
+ } else {
+ mViewHolder.dayGroupHeaderVisibility = View.GONE;
+ }
+ render(mViewHolder, mDetails, mRowId);
+ }
+ });
+ });
+ }
+
+ public void cancel() {
+ mIsCancelled = true;
+ }
}
/**
diff --git a/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java b/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java
index d285848..3aebbe9 100644
--- a/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java
+++ b/java/com/android/dialer/app/calllog/CallLogAsyncTaskUtil.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 The Android Open Source Project
+ * Copyright (C) 2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +21,6 @@
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
-import android.os.AsyncTask;
import android.provider.CallLog;
import android.provider.VoicemailContract.Voicemails;
import android.text.TextUtils;
@@ -52,23 +52,18 @@
}
asyncTaskExecutor.submit(
- Tasks.MARK_VOICEMAIL_READ,
- new AsyncTask<Void, Void, Void>() {
- @Override
- public Void doInBackground(Void... params) {
- ContentValues values = new ContentValues();
- values.put(Voicemails.IS_READ, true);
- // "External" changes to the database will be automatically marked as dirty, but this
- // voicemail might be from dialer so it need to be marked manually.
- values.put(Voicemails.DIRTY, 1);
- if (context
- .getContentResolver()
- .update(voicemailUri, values, Voicemails.IS_READ + " = 0", null)
- > 0) {
- uploadVoicemailLocalChangesToServer(context);
- CallLogNotificationsService.markAllNewVoicemailsAsOld(context);
- }
- return null;
+ Tasks.MARK_VOICEMAIL_READ, () -> {
+ ContentValues values = new ContentValues();
+ values.put(Voicemails.IS_READ, true);
+ // "External" changes to the database will be automatically marked as dirty, but this
+ // voicemail might be from dialer so it need to be marked manually.
+ values.put(Voicemails.DIRTY, 1);
+ if (context
+ .getContentResolver()
+ .update(voicemailUri, values, Voicemails.IS_READ + " = 0", null)
+ > 0) {
+ uploadVoicemailLocalChangesToServer(context);
+ CallLogNotificationsService.markAllNewVoicemailsAsOld(context);
}
});
}
@@ -81,22 +76,13 @@
initTaskExecutor();
}
- asyncTaskExecutor.submit(
- Tasks.DELETE_VOICEMAIL,
- new AsyncTask<Void, Void, Void>() {
- @Override
- public Void doInBackground(Void... params) {
- deleteVoicemailSynchronous(context, voicemailUri);
- return null;
- }
-
- @Override
- public void onPostExecute(Void result) {
- if (callLogAsyncTaskListener != null) {
- callLogAsyncTaskListener.onDeleteVoicemail();
- }
- }
- });
+ asyncTaskExecutor.submit(Tasks.DELETE_VOICEMAIL,
+ () -> deleteVoicemailSynchronous(context, voicemailUri),
+ () -> {
+ if (callLogAsyncTaskListener != null) {
+ callLogAsyncTaskListener.onDeleteVoicemail();
+ }
+ });
}
public static void deleteVoicemailSynchronous(Context context, Uri voicemailUri) {
@@ -117,35 +103,28 @@
initTaskExecutor();
}
- asyncTaskExecutor.submit(
- Tasks.MARK_CALL_READ,
- new AsyncTask<Void, Void, Void>() {
- @Override
- public Void doInBackground(Void... params) {
+ asyncTaskExecutor.submit(Tasks.MARK_CALL_READ, () -> {
+ StringBuilder where = new StringBuilder();
+ where.append(CallLog.Calls.TYPE).append(" = ").append(CallLog.Calls.MISSED_TYPE);
+ where.append(" AND ");
- StringBuilder where = new StringBuilder();
- where.append(CallLog.Calls.TYPE).append(" = ").append(CallLog.Calls.MISSED_TYPE);
- where.append(" AND ");
+ Long[] callIdLongs = new Long[callIds.length];
+ for (int i = 0; i < callIds.length; i++) {
+ callIdLongs[i] = callIds[i];
+ }
+ where
+ .append(CallLog.Calls._ID)
+ .append(" IN (" + TextUtils.join(",", callIdLongs) + ")");
- Long[] callIdLongs = new Long[callIds.length];
- for (int i = 0; i < callIds.length; i++) {
- callIdLongs[i] = callIds[i];
- }
- where
- .append(CallLog.Calls._ID)
- .append(" IN (" + TextUtils.join(",", callIdLongs) + ")");
-
- ContentValues values = new ContentValues(1);
- values.put(CallLog.Calls.IS_READ, "1");
- context
- .getContentResolver()
- .update(CallLog.Calls.CONTENT_URI, values, where.toString(), null);
- return null;
- }
- });
+ ContentValues values = new ContentValues(1);
+ values.put(CallLog.Calls.IS_READ, "1");
+ context
+ .getContentResolver()
+ .update(CallLog.Calls.CONTENT_URI, values, where.toString(), null);
+ });
}
- /** The enumeration of {@link AsyncTask} objects used in this class. */
+ /** The enumeration of objects used in this class. */
public enum Tasks {
DELETE_VOICEMAIL,
MARK_VOICEMAIL_READ,
diff --git a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
index 544f1bc..6858df2 100644
--- a/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
+++ b/java/com/android/dialer/app/calllog/CallLogListItemViewHolder.java
@@ -30,7 +30,6 @@
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
-import android.os.AsyncTask;
import android.provider.BlockedNumberContract;
import android.provider.CallLog;
import android.provider.CallLog.Calls;
@@ -229,7 +228,7 @@
public CharSequence dayGroupHeaderText;
public boolean isAttachedToWindow;
- public AsyncTask<Void, Void, ?> asyncTask;
+ public CallLogAdapter.LoadDataTaskInterface asyncTask;
private CallDetailsEntries callDetailsEntries;
private CallLogListItemViewHolder(
@@ -1095,7 +1094,7 @@
ContactSource.Type contactSourceType);
}
- private static class DeleteCallTask extends AsyncTask<Void, Void, Void> {
+ private static class DeleteCallTask implements Runnable {
// Using a weak reference to hold the Context so that there is no memory leak.
private final WeakReference<Context> contextWeakReference;
@@ -1106,15 +1105,15 @@
this.callIdsStr = concatCallIds(callIdsArray);
}
- @Override
// Suppress the lint check here as the user will not be able to see call log entries if
// permission.WRITE_CALL_LOG is not granted.
@SuppressLint("MissingPermission")
@RequiresPermission(value = permission.WRITE_CALL_LOG)
- protected Void doInBackground(Void... params) {
+ @Override
+ public void run() {
Context context = contextWeakReference.get();
if (context == null) {
- return null;
+ return;
}
if (callIdsStr != null) {
@@ -1128,13 +1127,8 @@
.getContentResolver()
.notifyChange(Calls.CONTENT_URI, null);
}
-
- return null;
}
- @Override
- public void onPostExecute(Void result) {}
-
private String concatCallIds(long[] callIds) {
if (callIds == null || callIds.length == 0) {
return null;
diff --git a/java/com/android/dialer/app/voicemail/VoicemailPlaybackPresenter.java b/java/com/android/dialer/app/voicemail/VoicemailPlaybackPresenter.java
index cd67296..7a479a6 100644
--- a/java/com/android/dialer/app/voicemail/VoicemailPlaybackPresenter.java
+++ b/java/com/android/dialer/app/voicemail/VoicemailPlaybackPresenter.java
@@ -26,9 +26,9 @@
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.Uri;
-import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
+import android.os.Looper;
import android.os.PowerManager;
import android.provider.CallLog;
import android.provider.VoicemailContract;
@@ -68,6 +68,7 @@
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
@@ -392,19 +393,13 @@
/** Checks to see if we have content available for this voicemail. */
protected void checkForContent(final OnContentCheckedListener callback) {
- asyncTaskExecutor.submit(
- Tasks.CHECK_FOR_CONTENT,
- new AsyncTask<Void, Void, Boolean>() {
- @Override
- public Boolean doInBackground(Void... params) {
- return queryHasContent(voicemailUri);
- }
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Handler handler = new Handler(Looper.getMainLooper());
- @Override
- public void onPostExecute(Boolean hasContent) {
- callback.onContentChecked(hasContent);
- }
- });
+ executor.execute(() -> {
+ final boolean hasContent = queryHasContent(voicemailUri);
+ handler.post(() -> callback.onContentChecked(hasContent));
+ });
}
private boolean queryHasContent(Uri voicemailUri) {
@@ -459,37 +454,28 @@
break;
}
- asyncTaskExecutor.submit(
- Tasks.SEND_FETCH_REQUEST,
- new AsyncTask<Void, Void, Void>() {
-
- @Override
- protected Void doInBackground(Void... voids) {
- try (Cursor cursor =
- context
- .getContentResolver()
- .query(
- voicemailUri, new String[] {Voicemails.SOURCE_PACKAGE}, null, null, null)) {
- String sourcePackage;
- if (!hasContent(cursor)) {
- LogUtil.e(
- "VoicemailPlaybackPresenter.requestContent",
- "mVoicemailUri does not return a SOURCE_PACKAGE");
- sourcePackage = null;
- } else {
- sourcePackage = cursor.getString(0);
- }
- // Send voicemail fetch request.
- Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, voicemailUri);
- intent.setPackage(sourcePackage);
- LogUtil.i(
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ executor.execute(() -> {
+ try (Cursor cursor = context.getContentResolver().query(
+ voicemailUri, new String[] {Voicemails.SOURCE_PACKAGE}, null, null, null)) {
+ String sourcePackage;
+ if (!hasContent(cursor)) {
+ LogUtil.e(
"VoicemailPlaybackPresenter.requestContent",
- "Sending ACTION_FETCH_VOICEMAIL to " + sourcePackage);
- context.sendBroadcast(intent);
- }
- return null;
- }
- });
+ "mVoicemailUri does not return a SOURCE_PACKAGE");
+ sourcePackage = null;
+ } else {
+ sourcePackage = cursor.getString(0);
+ }
+ // Send voicemail fetch request.
+ Intent intent = new Intent(VoicemailContract.ACTION_FETCH_VOICEMAIL, voicemailUri);
+ intent.setPackage(sourcePackage);
+ LogUtil.i(
+ "VoicemailPlaybackPresenter.requestContent",
+ "Sending ACTION_FETCH_VOICEMAIL to " + sourcePackage);
+ context.sendBroadcast(intent);
+ }
+ });
return true;
}
@@ -975,14 +961,6 @@
null);
}
- /** The enumeration of {@link AsyncTask} objects we use in this class. */
- public enum Tasks {
- CHECK_FOR_CONTENT,
- CHECK_CONTENT_AFTER_CHANGE,
- SHARE_VOICEMAIL,
- SEND_FETCH_REQUEST
- }
-
/** Contract describing the behaviour we need from the ui we are controlling. */
public interface PlaybackView {
@@ -1066,24 +1044,19 @@
@Override
public void onChange(boolean selfChange) {
- asyncTaskExecutor.submit(
- Tasks.CHECK_CONTENT_AFTER_CHANGE,
- new AsyncTask<Void, Void, Boolean>() {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Handler handler = new Handler(Looper.getMainLooper());
- @Override
- public Boolean doInBackground(Void... params) {
- return queryHasContent(voicemailUri);
- }
-
- @Override
- public void onPostExecute(Boolean hasContent) {
- if (hasContent && context != null && isWaitingForResult.getAndSet(false)) {
- context.getContentResolver().unregisterContentObserver(FetchResultHandler.this);
- showShareVoicemailButton(true);
- prepareContent();
- }
- }
- });
+ executor.execute(() -> {
+ final boolean hasContent = queryHasContent(voicemailUri);
+ handler.post(() -> {
+ if (hasContent && context != null && isWaitingForResult.getAndSet(false)) {
+ context.getContentResolver().unregisterContentObserver(FetchResultHandler.this);
+ showShareVoicemailButton(true);
+ prepareContent();
+ }
+ });
+ });
}
}
}
diff --git a/java/com/android/dialer/callstats/CallStatsDetailActivity.java b/java/com/android/dialer/callstats/CallStatsDetailActivity.java
index 93c4ccd..d30d3c8 100644
--- a/java/com/android/dialer/callstats/CallStatsDetailActivity.java
+++ b/java/com/android/dialer/callstats/CallStatsDetailActivity.java
@@ -20,8 +20,9 @@
import android.content.Intent;
import android.content.res.Resources;
-import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
import android.provider.CallLog.Calls;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.text.TextUtils;
@@ -50,6 +51,9 @@
import com.android.dialer.util.CallUtil;
import com.android.dialer.widget.LinearColorBar;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
/**
* Activity to display detailed information about a callstat item
*/
@@ -89,18 +93,21 @@
private CallStatsDetails mTotalData;
private String mNumber = null;
- private class UpdateContactTask extends AsyncTask<String, Void, ContactInfo> {
- @Override
- protected ContactInfo doInBackground(String... strings) {
- return mContactInfoHelper.lookupNumber(strings[0], strings[1]);
- }
+ private class UpdateContactTask {
- @Override
- protected void onPostExecute(ContactInfo info) {
- if (info != null) {
- mData.updateFromInfo(info);
- updateData();
- }
+ private void execute(String number, String countryIso) {
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Handler handler = new Handler(Looper.getMainLooper());
+
+ executor.execute(() -> {
+ final ContactInfo info = mContactInfoHelper.lookupNumber(number, countryIso);
+ handler.post(() -> {
+ if (info != null) {
+ mData.updateFromInfo(info);
+ updateData();
+ }
+ });
+ });
}
}
diff --git a/java/com/android/dialer/common/concurrent/AsyncTaskExecutor.java b/java/com/android/dialer/common/concurrent/AsyncTaskExecutor.java
index 6def128..32ff8b5 100644
--- a/java/com/android/dialer/common/concurrent/AsyncTaskExecutor.java
+++ b/java/com/android/dialer/common/concurrent/AsyncTaskExecutor.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 The Android Open Source Project
+ * Copyright (C) 2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,14 +17,12 @@
package com.android.dialer.common.concurrent;
-import android.os.AsyncTask;
-
import androidx.annotation.MainThread;
import java.util.concurrent.Executor;
/**
- * Interface used to submit {@link AsyncTask} objects to run in the background.
+ * Interface used to submit objects to run in the background.
*
* <p>This interface has a direct parallel with the {@link Executor} interface. It exists to
* decouple the mechanics of AsyncTask submission from the description of how that AsyncTask will
@@ -39,15 +38,9 @@
*/
public interface AsyncTaskExecutor {
- /**
- * Executes the given AsyncTask with the default Executor.
- *
- * <p>This method <b>must only be called from the ui thread</b>.
- *
- * <p>The identifier supplied is any Object that can be used to identify the task later. Most
- * commonly this will be an enum which the tests can also refer to. {@code null} is also accepted,
- * though of course this won't help in identifying the task later.
- */
@MainThread
- <T> AsyncTask<T, ?, ?> submit(Object identifier, AsyncTask<T, ?, ?> task, T... params);
+ void submit(Object identifier, Runnable runnable);
+
+ @MainThread
+ void submit(Object identifier, Runnable runnable, Runnable postExecuteRunnable);
}
diff --git a/java/com/android/dialer/common/concurrent/AsyncTaskExecutors.java b/java/com/android/dialer/common/concurrent/AsyncTaskExecutors.java
index 7c437df..d925b34 100644
--- a/java/com/android/dialer/common/concurrent/AsyncTaskExecutors.java
+++ b/java/com/android/dialer/common/concurrent/AsyncTaskExecutors.java
@@ -17,6 +17,8 @@
package com.android.dialer.common.concurrent;
import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
import androidx.annotation.MainThread;
@@ -50,16 +52,25 @@
static class SimpleAsyncTaskExecutor implements AsyncTaskExecutor {
private final Executor executor;
+ private final Handler handler;
public SimpleAsyncTaskExecutor(Executor executor) {
this.executor = executor;
+ this.handler = new Handler(Looper.getMainLooper());
}
@Override
@MainThread
- public <T> AsyncTask<T, ?, ?> submit(Object identifer, AsyncTask<T, ?, ?> task, T... params) {
+ public void submit(Object identifer, Runnable runnable) {
Assert.isMainThread();
- return task.executeOnExecutor(executor, params);
+ executor.execute(runnable);
+ }
+
+ @Override
+ public void submit(Object identifier, Runnable runnable, Runnable postExecuteRunnable) {
+ Assert.isMainThread();
+ executor.execute(runnable);
+ handler.post(postExecuteRunnable);
}
}
}
diff --git a/java/com/android/dialer/helplines/LoadHelplinesTask.java b/java/com/android/dialer/helplines/LoadHelplinesTask.java
index 049cdba..291dd36 100644
--- a/java/com/android/dialer/helplines/LoadHelplinesTask.java
+++ b/java/com/android/dialer/helplines/LoadHelplinesTask.java
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2019-2021 The LineageOS Project
- * Copyright (C) 2023 The LineageOS Project
+ * Copyright (C) 2019-2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,7 +16,8 @@
package com.android.dialer.helplines;
import android.content.res.Resources;
-import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
@@ -27,10 +27,12 @@
import org.lineageos.lib.phone.spn.Item;
import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
-public class LoadHelplinesTask extends AsyncTask<Void, Integer, List<HelplineItem>> {
+public class LoadHelplinesTask {
@NonNull
private final Resources mResources;
@@ -39,53 +41,64 @@
@NonNull
private final Callback mCallback;
+ private final ExecutorService mExecutor;
+ private final Handler mHandler;
+
LoadHelplinesTask(@NonNull Resources resources, @NonNull SubscriptionManager subManager,
@NonNull Callback callback) {
mResources = resources;
mSubManager = subManager;
mCallback = callback;
+
+ mExecutor = Executors.newSingleThreadExecutor();
+ mHandler = new Handler(Looper.getMainLooper());
}
- @Override
- protected List<HelplineItem> doInBackground(Void... voids) {
- List<HelplineItem> helplineList = new ArrayList<>();
- /* when the network's and the user's country iso differ from each other,
- * include the iso code in the name so one can be sure that the number is the correct one
- * (think of accidential roaming close to the country border) */
- boolean addCountryCode = false;
+ public void execute() {
+ mExecutor.execute(() -> {
+ final List<HelplineItem> helplineList = new ArrayList<>();
+ /* when the network's and the user's country iso differ from each other,
+ * include the iso code in the name so one can be sure that the number is the correct
+ * one (think of accidental roaming close to the country border) */
+ boolean addCountryCode = false;
- List<SubscriptionInfo> subList = getSubscriptionInfos();
- if (subList != null) {
- String localeCountryIso =
- mResources.getConfiguration().locale.getCountry().toLowerCase();
- List<String> alreadyProcessedMccs = new ArrayList<>();
- for (SubscriptionInfo subInfo : subList) {
- String subCountryIso = subInfo.getCountryIso();
- if (!subCountryIso.equals(localeCountryIso)) {
- addCountryCode = true;
- }
+ List<SubscriptionInfo> subList = getSubscriptionInfos();
+ if (subList != null) {
+ String localeCountryIso = mResources.getConfiguration().getLocales().get(0)
+ .getCountry().toLowerCase();
+ List<String> alreadyProcessedMccs = new ArrayList<>();
+ for (SubscriptionInfo subInfo : subList) {
+ String subCountryIso = subInfo.getCountryIso();
+ if (!subCountryIso.equals(localeCountryIso)) {
+ addCountryCode = true;
+ }
- String mcc = String.valueOf(subInfo.getMcc());
- if (alreadyProcessedMccs.contains(mcc)) {
- continue;
- }
- alreadyProcessedMccs.add(mcc);
+ String mcc = subInfo.getMccString();
+ if (alreadyProcessedMccs.contains(mcc)) {
+ continue;
+ }
+ alreadyProcessedMccs.add(mcc);
- SensitivePhoneNumbers spn = SensitivePhoneNumbers.getInstance();
- ArrayList<Item> pns = spn.getSensitivePnInfosForMcc(mcc);
- int numPns = pns.size();
- for (int i = 0; i < numPns; i++) {
- Item item = pns.get(i);
- helplineList.add(new HelplineItem(mResources, item,
- addCountryCode ? subCountryIso : ""));
- publishProgress(Math.round(i * 100 / numPns / subList.size()));
+ SensitivePhoneNumbers spn = SensitivePhoneNumbers.getInstance();
+ ArrayList<Item> pns = spn.getSensitivePnInfosForMcc(mcc);
+ int numPns = pns.size();
+ for (int i = 0; i < numPns; i++) {
+ Item item = pns.get(i);
+ helplineList.add(new HelplineItem(mResources, item,
+ addCountryCode ? subCountryIso : ""));
+ final int currentItem = i;
+ mHandler.post(() -> {
+ int progress = Math.round(currentItem * 100f / numPns / subList.size());
+ mCallback.onLoadListProgress(progress);
+ });
+ }
}
}
- }
- Collections.sort(helplineList, (a, b) -> a.getName().compareTo(b.getName()));
+ helplineList.sort(Comparator.comparing(HelplineItem::getName));
- return helplineList;
+ mHandler.post(() -> mCallback.onLoadCompleted(helplineList));
+ });
}
private List<SubscriptionInfo> getSubscriptionInfos() {
@@ -101,18 +114,6 @@
return subList;
}
- @Override
- protected void onProgressUpdate(Integer... values) {
- if (values.length > 0) {
- mCallback.onLoadListProgress(values[0]);
- }
- }
-
- @Override
- protected void onPostExecute(List<HelplineItem> list) {
- mCallback.onLoadCompleted(list);
- }
-
interface Callback {
void onLoadListProgress(int progress);
diff --git a/java/com/android/dialer/shortcuts/PeriodicJobService.java b/java/com/android/dialer/shortcuts/PeriodicJobService.java
index 038a820..7d65b2a 100644
--- a/java/com/android/dialer/shortcuts/PeriodicJobService.java
+++ b/java/com/android/dialer/shortcuts/PeriodicJobService.java
@@ -102,7 +102,7 @@
LogUtil.enterBlock("PeriodicJobService.onStopJob");
if (refreshShortcutsTask != null) {
- refreshShortcutsTask.cancel(false /* mayInterruptIfRunning */);
+ refreshShortcutsTask.cancel();
}
return false;
}
diff --git a/java/com/android/dialer/shortcuts/RefreshShortcutsTask.java b/java/com/android/dialer/shortcuts/RefreshShortcutsTask.java
index 360aea4..a06f0b3 100644
--- a/java/com/android/dialer/shortcuts/RefreshShortcutsTask.java
+++ b/java/com/android/dialer/shortcuts/RefreshShortcutsTask.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2016 The Android Open Source Project
+ * Copyright (C) 2023 The LineageOS Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,53 +19,57 @@
import android.app.job.JobParameters;
import android.app.job.JobService;
-import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
-import androidx.annotation.MainThread;
import androidx.annotation.NonNull;
-import androidx.annotation.WorkerThread;
-import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
-/** {@link AsyncTask} used by the periodic job service to refresh dynamic and pinned shortcuts. */
-final class RefreshShortcutsTask extends AsyncTask<JobParameters, Void, JobParameters> {
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+
+/** Class used by the periodic job service to refresh dynamic and pinned shortcuts. */
+final class RefreshShortcutsTask {
private final JobService jobService;
+ private final ExecutorService executor = Executors.newSingleThreadExecutor();
+ private final Handler handler = new Handler(Looper.getMainLooper());
+
+ private boolean mIsCancelled = false;
RefreshShortcutsTask(@NonNull JobService jobService) {
this.jobService = jobService;
}
- /** @param params array with length 1, provided from PeriodicJobService */
- @Override
- @NonNull
- @WorkerThread
- protected JobParameters doInBackground(JobParameters... params) {
- Assert.isWorkerThread();
- LogUtil.enterBlock("RefreshShortcutsTask.doInBackground");
+ /** @param param provided from PeriodicJobService */
+ public void execute(JobParameters param) {
+ executor.execute(() -> {
+ LogUtil.enterBlock("RefreshShortcutsTask.doInBackground");
- // Dynamic shortcuts are refreshed from the UI but icons can become stale, so update them
- // periodically using the job service.
- //
- // The reason that icons can become is stale is that there is no last updated timestamp for
- // pictures; there is only a last updated timestamp for the entire contact row, which changes
- // frequently (for example, when they are called their "times_contacted" is incremented).
- // Relying on such a spuriously updated timestamp would result in too frequent shortcut updates,
- // so instead we just allow the icon to become stale in the case that the contact's photo is
- // updated, and then rely on the job service to periodically force update it.
- new DynamicShortcuts(jobService, new IconFactory(jobService)).updateIcons(); // Blocking
- new PinnedShortcuts(jobService).refresh(); // Blocking
+ // Dynamic shortcuts are refreshed from the UI but icons can become stale, so update them
+ // periodically using the job service.
+ //
+ // The reason that icons can become is stale is that there is no last updated timestamp for
+ // pictures; there is only a last updated timestamp for the entire contact row, which changes
+ // frequently (for example, when they are called their "times_contacted" is incremented).
+ // Relying on such a spuriously updated timestamp would result in too frequent shortcut
+ // updates, so instead we just allow the icon to become stale in the case that the contact's
+ // photo is updated, and then rely on the job service to periodically force update it.
+ new DynamicShortcuts(jobService, new IconFactory(jobService)).updateIcons(); // Blocking
+ new PinnedShortcuts(jobService).refresh(); // Blocking
- return params[0];
+ if (!mIsCancelled) {
+ handler.post(() -> {
+ LogUtil.enterBlock("RefreshShortcutsTask.onPostExecute");
+ jobService.jobFinished(param, false /* needsReschedule */);
+ });
+ }
+ });
}
- @Override
- @MainThread
- protected void onPostExecute(JobParameters params) {
- Assert.isMainThread();
- LogUtil.enterBlock("RefreshShortcutsTask.onPostExecute");
-
- jobService.jobFinished(params, false /* needsReschedule */);
+ public void cancel() {
+ mIsCancelled = true;
}
}
diff --git a/java/com/android/dialer/shortcuts/ShortcutUsageReporter.java b/java/com/android/dialer/shortcuts/ShortcutUsageReporter.java
index 3cd719b..f3ecc73 100644
--- a/java/com/android/dialer/shortcuts/ShortcutUsageReporter.java
+++ b/java/com/android/dialer/shortcuts/ShortcutUsageReporter.java
@@ -23,7 +23,8 @@
import android.content.pm.ShortcutManager;
import android.database.Cursor;
import android.net.Uri;
-import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.PhoneLookup;
import android.text.TextUtils;
@@ -36,8 +37,9 @@
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
-import com.android.dialer.common.concurrent.AsyncTaskExecutor;
-import com.android.dialer.common.concurrent.AsyncTaskExecutors;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
/**
* Reports outgoing calls as shortcut usage.
@@ -50,8 +52,6 @@
*/
public class ShortcutUsageReporter {
- private static final AsyncTaskExecutor EXECUTOR = AsyncTaskExecutors.createThreadPoolExecutor();
-
/**
* Called when an outgoing call is added to the call list in order to report outgoing calls as
* shortcut usage. This should be called exactly once for each outgoing call.
@@ -71,36 +71,36 @@
return;
}
- EXECUTOR.submit(Task.ID, new Task(context), phoneNumber);
+ new Task(context).execute(phoneNumber);
}
- private static final class Task extends AsyncTask<String, Void, Void> {
+ private static final class Task {
private static final String ID = "ShortcutUsageReporter.Task";
private final Context context;
+ private final ExecutorService executor = Executors.newSingleThreadExecutor();
+ private final Handler handler = new Handler(Looper.getMainLooper());
+
public Task(Context context) {
this.context = context;
}
- /** @param phoneNumbers array with exactly one non-empty phone number */
- @Override
- @WorkerThread
- protected Void doInBackground(@NonNull String... phoneNumbers) {
- Assert.isWorkerThread();
+ /** @param phoneNumber non-empty phone number */
+ public void execute(@NonNull String phoneNumber) {
+ executor.execute(() -> {
+ String lookupKey = queryForLookupKey(phoneNumber);
+ if (!TextUtils.isEmpty(lookupKey)) {
+ LogUtil.i("ShortcutUsageReporter.backgroundLogUsage", "%s", lookupKey);
+ ShortcutManager shortcutManager =
+ (ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE);
- String lookupKey = queryForLookupKey(phoneNumbers[0]);
- if (!TextUtils.isEmpty(lookupKey)) {
- LogUtil.i("ShortcutUsageReporter.backgroundLogUsage", "%s", lookupKey);
- ShortcutManager shortcutManager =
- (ShortcutManager) context.getSystemService(Context.SHORTCUT_SERVICE);
-
- // Note: There may not currently exist a shortcut with the provided key, but it is logged
- // anyway, so that launcher applications at least have the information should the shortcut
- // be created in the future.
- shortcutManager.reportShortcutUsed(lookupKey);
- }
- return null;
+ // Note: There may not currently exist a shortcut with the provided key, but it is logged
+ // anyway, so that launcher applications at least have the information should the shortcut
+ // be created in the future.
+ shortcutManager.reportShortcutUsed(lookupKey);
+ }
+ });
}
@Nullable
diff --git a/java/com/android/dialer/smartdial/SmartDialCursorLoader.java b/java/com/android/dialer/smartdial/SmartDialCursorLoader.java
index 205362c..314bbd6 100644
--- a/java/com/android/dialer/smartdial/SmartDialCursorLoader.java
+++ b/java/com/android/dialer/smartdial/SmartDialCursorLoader.java
@@ -16,11 +16,13 @@
package com.android.dialer.smartdial;
-import android.content.AsyncTaskLoader;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.provider.ContactsContract.CommonDataKinds.Phone;
+
+import androidx.loader.content.AsyncTaskLoader;
+
import com.android.dialer.common.LogUtil;
import com.android.dialer.database.Database;
import com.android.dialer.database.DialerDatabaseHelper;