Skip to content
Snippets Groups Projects
Commit ae8fb7fa authored by Roshan Pius's avatar Roshan Pius Committed by Android (Google) Code Review
Browse files

Merge "Introduce `NoOpResolverComparator`." into main

parents fc6ff5a9 9f560c6e
No related branches found
No related tags found
No related merge requests found
/*
* Copyright 2024 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.
*/
package com.android.internal.app;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.os.Message;
import android.os.UserHandle;
import androidx.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import com.android.internal.app.chooser.TargetInfo;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* A basic {@link AbstractResolverComparator} implementation that sorts items into the same order as
* they appeared in the list provided to {@link #doCompute(List)}. "Unknown" items that didn't
* appear in the original list are ordered arbitrarily at the end.
*/
public class NoOpResolverComparator extends AbstractResolverComparator {
@Nullable
private List<ResolveInfo> mOriginalTargetOrder = null;
public NoOpResolverComparator(
Context launchedFromContext,
Intent intent,
List<UserHandle> targetUserSpaceList) {
super(launchedFromContext, intent, targetUserSpaceList);
}
@Override
public void doCompute(List<ResolvedComponentInfo> targets) {
mOriginalTargetOrder = new ArrayList<>();
for (ResolvedComponentInfo target : targets) {
mOriginalTargetOrder.add(target.getResolveInfoAt(0));
}
afterCompute();
}
@Override
public int compare(ResolveInfo lhs, ResolveInfo rhs) {
Comparator<ResolveInfo> c = Comparator.comparingDouble(r -> getScore((ResolveInfo) r));
c = c.reversed();
return c.compare(lhs, rhs);
}
@Override
public float getScore(TargetInfo targetInfo) {
return getScore(targetInfo.getResolveInfo());
}
@Override
public void handleResultMessage(Message message) {}
@VisibleForTesting
public float getScore(ResolveInfo resolveInfo) {
if (!mOriginalTargetOrder.contains(resolveInfo)) {
return 0;
}
// Assign a score from 1 (for the first item in the original list) down
// to 1/(n+1) for the last item (which is still greater than 0, the
// score we assign to any unknown items).
float rank = mOriginalTargetOrder.indexOf(resolveInfo);
return 1.0f - (rank / (1 + mOriginalTargetOrder.size()));
}
}
...@@ -170,6 +170,10 @@ public class ResolverActivity extends Activity implements ...@@ -170,6 +170,10 @@ public class ResolverActivity extends Activity implements
// Expected to be true if this object is ResolverActivity or is ResolverWrapperActivity. // Expected to be true if this object is ResolverActivity or is ResolverWrapperActivity.
private final boolean mIsIntentPicker; private final boolean mIsIntentPicker;
// Whether this activity was instantiated with a specialized constructor that predefines a list
// of resolutions to be displayed for the target intent (as in, e.g., the NFC use case).
private boolean mHasSubclassSpecifiedResolutions;
// Whether or not this activity supports choosing a default handler for the intent. // Whether or not this activity supports choosing a default handler for the intent.
@VisibleForTesting @VisibleForTesting
protected boolean mSupportsAlwaysUseOption; protected boolean mSupportsAlwaysUseOption;
...@@ -421,6 +425,8 @@ public class ResolverActivity extends Activity implements ...@@ -421,6 +425,8 @@ public class ResolverActivity extends Activity implements
setTheme(appliedThemeResId()); setTheme(appliedThemeResId());
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
mHasSubclassSpecifiedResolutions = (rList != null);
mQuietModeManager = createQuietModeManager(); mQuietModeManager = createQuietModeManager();
// Determine whether we should show that intent is forwarded // Determine whether we should show that intent is forwarded
...@@ -1698,17 +1704,25 @@ public class ResolverActivity extends Activity implements ...@@ -1698,17 +1704,25 @@ public class ResolverActivity extends Activity implements
isAudioCaptureDevice, initialIntentsUserSpace); isAudioCaptureDevice, initialIntentsUserSpace);
} }
private AbstractResolverComparator makeResolverComparator(UserHandle userHandle) {
if (mHasSubclassSpecifiedResolutions) {
return new NoOpResolverComparator(
this, getTargetIntent(), getResolverRankerServiceUserHandleList(userHandle));
} else {
return new ResolverRankerServiceResolverComparator(
this,
getTargetIntent(),
getReferrerPackageName(),
null,
null,
getResolverRankerServiceUserHandleList(userHandle));
}
}
@VisibleForTesting @VisibleForTesting
protected ResolverListController createListController(UserHandle userHandle) { protected ResolverListController createListController(UserHandle userHandle) {
UserHandle queryIntentsUser = getQueryIntentsUser(userHandle); UserHandle queryIntentsUser = getQueryIntentsUser(userHandle);
ResolverRankerServiceResolverComparator resolverComparator = AbstractResolverComparator resolverComparator = makeResolverComparator(userHandle);
new ResolverRankerServiceResolverComparator(
this,
getTargetIntent(),
getReferrerPackageName(),
null,
null,
getResolverRankerServiceUserHandleList(userHandle));
return new ResolverListController( return new ResolverListController(
this, this,
mPm, mPm,
......
/*
* Copyright (C) 2024 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.
*/
package com.android.internal.app;
import static com.google.common.truth.Truth.assertThat;
import android.content.Intent;
import android.os.UserHandle;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/** Unit tests for the behavior of {@link NoOpResolverComparator}. */
@RunWith(AndroidJUnit4.class)
public class NoOpResolverComparatorTest {
private static final UserHandle PERSONAL_USER_HANDLE = InstrumentationRegistry
.getInstrumentation().getTargetContext().getUser();
public final ResolvedComponentInfo resolution1 =
ResolverDataProvider.createResolvedComponentInfo(1, PERSONAL_USER_HANDLE);
public final ResolvedComponentInfo resolution2 =
ResolverDataProvider.createResolvedComponentInfo(2, PERSONAL_USER_HANDLE);
public final ResolvedComponentInfo resolution3 =
ResolverDataProvider.createResolvedComponentInfo(3, PERSONAL_USER_HANDLE);
public final ResolvedComponentInfo resolution4 =
ResolverDataProvider.createResolvedComponentInfo(4, PERSONAL_USER_HANDLE);
private NoOpResolverComparator mComparator;
@Before
public void setUp() {
mComparator = new NoOpResolverComparator(
InstrumentationRegistry.getInstrumentation().getTargetContext(),
new Intent(),
List.of(PERSONAL_USER_HANDLE));
}
@Test
public void testKnownItemsSortInOriginalOrder() {
List<ResolvedComponentInfo> originalOrder = List.of(resolution1, resolution2, resolution3);
mComparator.doCompute(originalOrder);
List<ResolvedComponentInfo> queryOrder = new ArrayList<>(
List.of(resolution2, resolution3, resolution1));
Collections.sort(queryOrder, mComparator);
assertThat(queryOrder).isEqualTo(originalOrder);
}
@Test
public void testUnknownItemsSortAfterKnownItems() {
List<ResolvedComponentInfo> originalOrder = List.of(resolution1, resolution2);
mComparator.doCompute(originalOrder);
// Query includes the unknown `resolution4`.
List<ResolvedComponentInfo> queryOrder = new ArrayList<>(
List.of(resolution2, resolution4, resolution1));
Collections.sort(queryOrder, mComparator);
assertThat(queryOrder).isEqualTo(List.of(resolution1, resolution2, resolution4));
}
@Test
public void testKnownItemsGetNonZeroScoresInOrder() {
List<ResolvedComponentInfo> originalOrder = List.of(resolution1, resolution2);
mComparator.doCompute(originalOrder);
float score1 = mComparator.getScore(resolution1.getResolveInfoAt(0));
float score2 = mComparator.getScore(resolution2.getResolveInfoAt(0));
assertThat(score1).isEqualTo(1.0f);
assertThat(score2).isLessThan(score1);
assertThat(score2).isGreaterThan(0.0f);
}
@Test
public void testUnknownItemsGetZeroScore() {
List<ResolvedComponentInfo> originalOrder = List.of(resolution1, resolution2);
mComparator.doCompute(originalOrder);
assertThat(mComparator.getScore(resolution3.getResolveInfoAt(0))).isEqualTo(0.0f);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment