summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/intentresolver/ChooserListAdapter.java46
-rw-r--r--java/src/com/android/intentresolver/ResolverActivity.java14
-rw-r--r--java/src/com/android/intentresolver/ResolverInfoHelpers.kt34
-rw-r--r--java/src/com/android/intentresolver/ResolverListAdapter.java103
-rw-r--r--java/src/com/android/intentresolver/ResolverListController.java2
5 files changed, 129 insertions, 70 deletions
diff --git a/java/src/com/android/intentresolver/ChooserListAdapter.java b/java/src/com/android/intentresolver/ChooserListAdapter.java
index d1101f1e..a9ed983d 100644
--- a/java/src/com/android/intentresolver/ChooserListAdapter.java
+++ b/java/src/com/android/intentresolver/ChooserListAdapter.java
@@ -43,6 +43,9 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
+import androidx.annotation.MainThread;
+import androidx.annotation.WorkerThread;
+
import com.android.intentresolver.chooser.DisplayResolveInfo;
import com.android.intentresolver.chooser.MultiDisplayResolveInfo;
import com.android.intentresolver.chooser.NotSelectableTargetInfo;
@@ -567,7 +570,7 @@ public class ChooserListAdapter extends ResolverListAdapter {
protected boolean shouldAddResolveInfo(DisplayResolveInfo dri) {
// Checks if this info is already listed in callerTargets.
for (TargetInfo existingInfo : mCallerTargets) {
- if (mResolverListCommunicator.resolveInfoMatch(
+ if (ResolveInfoHelpers.resolveInfoMatch(
dri.getResolveInfo(), existingInfo.getResolveInfo())) {
return false;
}
@@ -658,30 +661,23 @@ public class ChooserListAdapter extends ResolverListAdapter {
* in the head of input list and fill the tail with other elements in undetermined order.
*/
@Override
- AsyncTask<List<ResolvedComponentInfo>,
- Void,
- List<ResolvedComponentInfo>> createSortingTask(boolean doPostProcessing) {
- return new AsyncTask<List<ResolvedComponentInfo>,
- Void,
- List<ResolvedComponentInfo>>() {
- @Override
- protected List<ResolvedComponentInfo> doInBackground(
- List<ResolvedComponentInfo>... params) {
- Trace.beginSection("ChooserListAdapter#SortingTask");
- mResolverListController.topK(params[0], mMaxRankedTargets);
- Trace.endSection();
- return params[0];
- }
-
- @Override
- protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
- processSortedList(sortedComponents, doPostProcessing);
- if (doPostProcessing) {
- mResolverListCommunicator.updateProfileViewButton();
- notifyDataSetChanged();
- }
- }
- };
+ @WorkerThread
+ protected void sortComponents(List<ResolvedComponentInfo> components) {
+ Trace.beginSection("ChooserListAdapter#SortingTask");
+ mResolverListController.topK(components, mMaxRankedTargets);
+ Trace.endSection();
}
+ @Override
+ @MainThread
+ protected void onComponentsSorted(
+ @Nullable List<ResolvedComponentInfo> sortedComponents, boolean doPostProcessing) {
+ processSortedList(sortedComponents, doPostProcessing);
+ if (doPostProcessing) {
+ mResolverListCommunicator.updateProfileViewButton();
+ //TODO: this method is different from super's only in that `notifyDataSetChanged` is
+ // called conditionally here; is it really important?
+ notifyDataSetChanged();
+ }
+ }
}
diff --git a/java/src/com/android/intentresolver/ResolverActivity.java b/java/src/com/android/intentresolver/ResolverActivity.java
index 0d3becc2..47a8bf2a 100644
--- a/java/src/com/android/intentresolver/ResolverActivity.java
+++ b/java/src/com/android/intentresolver/ResolverActivity.java
@@ -2262,20 +2262,6 @@ public class ResolverActivity extends FragmentActivity implements
mRetainInOnStop = retainInOnStop;
}
- /**
- * Check a simple match for the component of two ResolveInfos.
- */
- @Override // ResolverListCommunicator
- public final boolean resolveInfoMatch(ResolveInfo lhs, ResolveInfo rhs) {
- return lhs == null ? rhs == null
- : lhs.activityInfo == null ? rhs.activityInfo == null
- : Objects.equals(lhs.activityInfo.name, rhs.activityInfo.name)
- && Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName)
- // Comparing against resolveInfo.userHandle in case cloned apps are present,
- // as they will have the same activityInfo.
- && Objects.equals(lhs.userHandle, rhs.userHandle);
- }
-
private boolean inactiveListAdapterHasItems() {
if (!shouldShowTabs()) {
return false;
diff --git a/java/src/com/android/intentresolver/ResolverInfoHelpers.kt b/java/src/com/android/intentresolver/ResolverInfoHelpers.kt
new file mode 100644
index 00000000..8d1d8658
--- /dev/null
+++ b/java/src/com/android/intentresolver/ResolverInfoHelpers.kt
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@file:JvmName("ResolveInfoHelpers")
+
+package com.android.intentresolver
+
+import android.content.pm.ActivityInfo
+import android.content.pm.ResolveInfo
+
+fun resolveInfoMatch(lhs: ResolveInfo?, rhs: ResolveInfo?): Boolean =
+ (lhs === rhs) ||
+ ((lhs != null && rhs != null) &&
+ activityInfoMatch(lhs.activityInfo, rhs.activityInfo) &&
+ // Comparing against resolveInfo.userHandle in case cloned apps are present,
+ // as they will have the same activityInfo.
+ lhs.userHandle == rhs.userHandle)
+
+private fun activityInfoMatch(lhs: ActivityInfo?, rhs: ActivityInfo?): Boolean =
+ (lhs === rhs) ||
+ (lhs != null && rhs != null && lhs.name == rhs.name && lhs.packageName == rhs.packageName)
diff --git a/java/src/com/android/intentresolver/ResolverListAdapter.java b/java/src/com/android/intentresolver/ResolverListAdapter.java
index 282a672f..14ce0e0e 100644
--- a/java/src/com/android/intentresolver/ResolverListAdapter.java
+++ b/java/src/com/android/intentresolver/ResolverListAdapter.java
@@ -28,6 +28,7 @@ import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
+import android.os.Handler;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
@@ -42,6 +43,9 @@ import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
+import androidx.annotation.MainThread;
+import androidx.annotation.WorkerThread;
+
import com.android.intentresolver.chooser.DisplayResolveInfo;
import com.android.intentresolver.chooser.TargetInfo;
import com.android.intentresolver.icons.TargetDataLoader;
@@ -53,6 +57,7 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.Executor;
public class ResolverListAdapter extends BaseAdapter {
private static final String TAG = "ResolverListAdapter";
@@ -75,6 +80,8 @@ public class ResolverListAdapter extends BaseAdapter {
private final Set<DisplayResolveInfo> mRequestedIcons = new HashSet<>();
private final Set<DisplayResolveInfo> mRequestedLabels = new HashSet<>();
+ private final Executor mBgExecutor;
+ private final Handler mMainHandler;
private ResolveInfo mLastChosen;
private DisplayResolveInfo mOtherProfile;
@@ -103,6 +110,37 @@ public class ResolverListAdapter extends BaseAdapter {
ResolverListCommunicator resolverListCommunicator,
UserHandle initialIntentsUserSpace,
TargetDataLoader targetDataLoader) {
+ this(
+ context,
+ payloadIntents,
+ initialIntents,
+ rList,
+ filterLastUsed,
+ resolverListController,
+ userHandle,
+ targetIntent,
+ resolverListCommunicator,
+ initialIntentsUserSpace,
+ targetDataLoader,
+ AsyncTask.SERIAL_EXECUTOR,
+ context.getMainThreadHandler());
+ }
+
+ @VisibleForTesting
+ public ResolverListAdapter(
+ Context context,
+ List<Intent> payloadIntents,
+ Intent[] initialIntents,
+ List<ResolveInfo> rList,
+ boolean filterLastUsed,
+ ResolverListController resolverListController,
+ UserHandle userHandle,
+ Intent targetIntent,
+ ResolverListCommunicator resolverListCommunicator,
+ UserHandle initialIntentsUserSpace,
+ TargetDataLoader targetDataLoader,
+ Executor bgExecutor,
+ Handler mainHandler) {
mContext = context;
mIntents = payloadIntents;
mInitialIntents = initialIntents;
@@ -117,6 +155,8 @@ public class ResolverListAdapter extends BaseAdapter {
mTargetIntent = targetIntent;
mResolverListCommunicator = resolverListCommunicator;
mInitialIntentsUserSpace = initialIntentsUserSpace;
+ mBgExecutor = bgExecutor;
+ mMainHandler = mainHandler;
}
public final DisplayResolveInfo getFirstDisplayResolveInfo() {
@@ -402,35 +442,42 @@ public class ResolverListAdapter extends BaseAdapter {
// Send an "incomplete" list-ready while the async task is running.
postListReadyRunnable(doPostProcessing, /* rebuildCompleted */ false);
- createSortingTask(doPostProcessing).execute(filteredResolveList);
+ mBgExecutor.execute(() -> {
+ List<ResolvedComponentInfo> sortedComponents = null;
+ //TODO: the try-catch logic here is to formally match the AsyncTask's behavior.
+ // Empirically, we don't need it as in the case on an exception, the app will crash and
+ // `onComponentsSorted` won't be invoked.
+ try {
+ sortComponents(filteredResolveList);
+ sortedComponents = filteredResolveList;
+ } catch (Throwable t) {
+ Log.e(TAG, "Failed to sort components", t);
+ throw t;
+ } finally {
+ final List<ResolvedComponentInfo> result = sortedComponents;
+ mMainHandler.post(() -> onComponentsSorted(result, doPostProcessing));
+ }
+ });
return false;
}
- AsyncTask<List<ResolvedComponentInfo>,
- Void,
- List<ResolvedComponentInfo>> createSortingTask(boolean doPostProcessing) {
- return new AsyncTask<List<ResolvedComponentInfo>,
- Void,
- List<ResolvedComponentInfo>>() {
- @Override
- protected List<ResolvedComponentInfo> doInBackground(
- List<ResolvedComponentInfo>... params) {
- mResolverListController.sort(params[0]);
- return params[0];
- }
- @Override
- protected void onPostExecute(List<ResolvedComponentInfo> sortedComponents) {
- processSortedList(sortedComponents, doPostProcessing);
- notifyDataSetChanged();
- if (doPostProcessing) {
- mResolverListCommunicator.updateProfileViewButton();
- }
- }
- };
+ @WorkerThread
+ protected void sortComponents(List<ResolvedComponentInfo> components) {
+ mResolverListController.sort(components);
}
- protected void processSortedList(List<ResolvedComponentInfo> sortedComponents,
- boolean doPostProcessing) {
+ @MainThread
+ protected void onComponentsSorted(
+ @Nullable List<ResolvedComponentInfo> sortedComponents, boolean doPostProcessing) {
+ processSortedList(sortedComponents, doPostProcessing);
+ notifyDataSetChanged();
+ if (doPostProcessing) {
+ mResolverListCommunicator.updateProfileViewButton();
+ }
+ }
+
+ protected void processSortedList(
+ @Nullable List<ResolvedComponentInfo> sortedComponents, boolean doPostProcessing) {
final int n = sortedComponents != null ? sortedComponents.size() : 0;
Trace.beginSection("ResolverListAdapter#processSortedList:" + n);
if (n != 0) {
@@ -509,7 +556,7 @@ public class ResolverListAdapter extends BaseAdapter {
mPostListReadyRunnable = null;
}
};
- mContext.getMainThreadHandler().post(mPostListReadyRunnable);
+ mMainHandler.post(mPostListReadyRunnable);
}
}
@@ -572,7 +619,7 @@ public class ResolverListAdapter extends BaseAdapter {
protected boolean shouldAddResolveInfo(DisplayResolveInfo dri) {
// Checks if this info is already listed in display.
for (DisplayResolveInfo existingInfo : mDisplayList) {
- if (mResolverListCommunicator
+ if (ResolveInfoHelpers
.resolveInfoMatch(dri.getResolveInfo(), existingInfo.getResolveInfo())) {
return false;
}
@@ -728,7 +775,7 @@ public class ResolverListAdapter extends BaseAdapter {
public void onDestroy() {
if (mPostListReadyRunnable != null) {
- mContext.getMainThreadHandler().removeCallbacks(mPostListReadyRunnable);
+ mMainHandler.removeCallbacks(mPostListReadyRunnable);
mPostListReadyRunnable = null;
}
if (mResolverListController != null) {
@@ -856,8 +903,6 @@ public class ResolverListAdapter extends BaseAdapter {
*/
interface ResolverListCommunicator {
- boolean resolveInfoMatch(ResolveInfo lhs, ResolveInfo rhs);
-
Intent getReplacementIntent(ActivityInfo activityInfo, Intent defIntent);
void onPostListReady(ResolverListAdapter listAdapter, boolean updateUi,
diff --git a/java/src/com/android/intentresolver/ResolverListController.java b/java/src/com/android/intentresolver/ResolverListController.java
index d5a5fedf..cb56ab30 100644
--- a/java/src/com/android/intentresolver/ResolverListController.java
+++ b/java/src/com/android/intentresolver/ResolverListController.java
@@ -254,7 +254,6 @@ public class ResolverListController {
isComputed = true;
}
- @VisibleForTesting
@WorkerThread
public void sort(List<ResolvedComponentInfo> inputList) {
try {
@@ -273,7 +272,6 @@ public class ResolverListController {
}
}
- @VisibleForTesting
@WorkerThread
public void topK(List<ResolvedComponentInfo> inputList, int k) {
if (inputList == null || inputList.isEmpty() || k <= 0) {