Allow filtering of services

Test: ServiceListingTest
Bug: 260570119
Change-Id: Ib4740ba401667de62fa1a33334c2c1fbee25b760
Merged-In: Ib4740ba401667de62fa1a33334c2c1fbee25b760
This commit is contained in:
Julia Reynolds
2023-03-07 15:44:49 -05:00
parent f6228ade76
commit bbc68b5aa7
2 changed files with 111 additions and 4 deletions

View File

@@ -35,6 +35,7 @@ import android.util.Slog;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.function.Predicate;
/**
* Class for managing services matching a given intent and requesting a given permission.
@@ -51,12 +52,13 @@ public class ServiceListing {
private final HashSet<ComponentName> mEnabledServices = new HashSet<>();
private final List<ServiceInfo> mServices = new ArrayList<>();
private final List<Callback> mCallbacks = new ArrayList<>();
private final Predicate mValidator;
private boolean mListening;
private ServiceListing(Context context, String tag,
String setting, String intentAction, String permission, String noun,
boolean addDeviceLockedFlags) {
boolean addDeviceLockedFlags, Predicate validator) {
mContentResolver = context.getContentResolver();
mContext = context;
mTag = tag;
@@ -65,6 +67,7 @@ public class ServiceListing {
mPermission = permission;
mNoun = noun;
mAddDeviceLockedFlags = addDeviceLockedFlags;
mValidator = validator;
}
public void addCallback(Callback callback) {
@@ -137,7 +140,6 @@ public class ServiceListing {
final PackageManager pmWrapper = mContext.getPackageManager();
List<ResolveInfo> installedServices = pmWrapper.queryIntentServicesAsUser(
new Intent(mIntentAction), flags, user);
for (ResolveInfo resolveInfo : installedServices) {
ServiceInfo info = resolveInfo.serviceInfo;
@@ -148,6 +150,9 @@ public class ServiceListing {
+ mPermission);
continue;
}
if (mValidator != null && !mValidator.test(info)) {
continue;
}
mServices.add(info);
}
for (Callback callback : mCallbacks) {
@@ -194,6 +199,7 @@ public class ServiceListing {
private String mPermission;
private String mNoun;
private boolean mAddDeviceLockedFlags = false;
private Predicate mValidator;
public Builder(Context context) {
mContext = context;
@@ -224,6 +230,11 @@ public class ServiceListing {
return this;
}
public Builder setValidator(Predicate<ServiceInfo> validator) {
mValidator = validator;
return this;
}
/**
* Set to true to add support for both MATCH_DIRECT_BOOT_AWARE and
* MATCH_DIRECT_BOOT_UNAWARE flags when querying PackageManager. Required to get results
@@ -236,7 +247,7 @@ public class ServiceListing {
public ServiceListing build() {
return new ServiceListing(mContext, mTag, mSetting, mIntentAction, mPermission, mNoun,
mAddDeviceLockedFlags);
mAddDeviceLockedFlags, mValidator);
}
}
}

View File

@@ -18,20 +18,35 @@ package com.android.settingslib.applications;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyList;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import com.google.common.collect.ImmutableList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class ServiceListingTest {
@@ -39,10 +54,16 @@ public class ServiceListingTest {
private static final String TEST_INTENT = "com.example.intent";
private ServiceListing mServiceListing;
private Context mContext;
private PackageManager mPm;
@Before
public void setUp() {
mServiceListing = new ServiceListing.Builder(RuntimeEnvironment.application)
mPm = mock(PackageManager.class);
mContext = spy(ApplicationProvider.getApplicationContext());
when(mContext.getPackageManager()).thenReturn(mPm);
mServiceListing = new ServiceListing.Builder(mContext)
.setTag("testTag")
.setSetting(TEST_SETTING)
.setNoun("testNoun")
@@ -51,6 +72,81 @@ public class ServiceListingTest {
.build();
}
@Test
public void testValidator() {
ServiceInfo s1 = new ServiceInfo();
s1.permission = "testPermission";
s1.packageName = "pkg";
ServiceInfo s2 = new ServiceInfo();
s2.permission = "testPermission";
s2.packageName = "pkg2";
ResolveInfo r1 = new ResolveInfo();
r1.serviceInfo = s1;
ResolveInfo r2 = new ResolveInfo();
r2.serviceInfo = s2;
when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
ImmutableList.of(r1, r2));
mServiceListing = new ServiceListing.Builder(mContext)
.setTag("testTag")
.setSetting(TEST_SETTING)
.setNoun("testNoun")
.setIntentAction(TEST_INTENT)
.setValidator(info -> {
if (info.packageName.equals("pkg")) {
return true;
}
return false;
})
.setPermission("testPermission")
.build();
ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
mServiceListing.addCallback(callback);
mServiceListing.reload();
verify(mPm).queryIntentServicesAsUser(any(), anyInt(), anyInt());
ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
verify(callback, times(1)).onServicesReloaded(captor.capture());
assertThat(captor.getValue().size()).isEqualTo(1);
assertThat(captor.getValue().get(0)).isEqualTo(s1);
}
@Test
public void testNoValidator() {
ServiceInfo s1 = new ServiceInfo();
s1.permission = "testPermission";
s1.packageName = "pkg";
ServiceInfo s2 = new ServiceInfo();
s2.permission = "testPermission";
s2.packageName = "pkg2";
ResolveInfo r1 = new ResolveInfo();
r1.serviceInfo = s1;
ResolveInfo r2 = new ResolveInfo();
r2.serviceInfo = s2;
when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).thenReturn(
ImmutableList.of(r1, r2));
mServiceListing = new ServiceListing.Builder(mContext)
.setTag("testTag")
.setSetting(TEST_SETTING)
.setNoun("testNoun")
.setIntentAction(TEST_INTENT)
.setPermission("testPermission")
.build();
ServiceListing.Callback callback = mock(ServiceListing.Callback.class);
mServiceListing.addCallback(callback);
mServiceListing.reload();
verify(mPm).queryIntentServicesAsUser(any(), anyInt(), anyInt());
ArgumentCaptor<List<ServiceInfo>> captor = ArgumentCaptor.forClass(List.class);
verify(callback, times(1)).onServicesReloaded(captor.capture());
assertThat(captor.getValue().size()).isEqualTo(2);
}
@Test
public void testCallback() {
ServiceListing.Callback callback = mock(ServiceListing.Callback.class);