diff --git a/src/com/android/settings/search2/InstalledAppResultLoader.java b/src/com/android/settings/search2/InstalledAppResultLoader.java index 449e52c80f8..14735bdf355 100644 --- a/src/com/android/settings/search2/InstalledAppResultLoader.java +++ b/src/com/android/settings/search2/InstalledAppResultLoader.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.net.Uri; import android.os.UserHandle; @@ -41,11 +42,14 @@ public class InstalledAppResultLoader extends AsyncLoader> { private static final int NAME_NO_MATCH = -1; private static final int NAME_EXACT_MATCH = 0; + private static final Intent LAUNCHER_PROBE = new Intent(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER); private final String mQuery; private final UserManager mUserManager; private final PackageManagerWrapper mPackageManager; + public InstalledAppResultLoader(Context context, PackageManagerWrapper pmWrapper, String query) { super(context); @@ -67,7 +71,7 @@ public class InstalledAppResultLoader extends AsyncLoader> { | (user.isAdmin() ? PackageManager.MATCH_ANY_USER : 0), user.id); for (ApplicationInfo info : apps) { - if (info.isSystemApp()) { + if (!shouldIncludeAsCandidate(info, user)) { continue; } final CharSequence label = info.loadLabel(pm); @@ -91,6 +95,22 @@ public class InstalledAppResultLoader extends AsyncLoader> { return results; } + private boolean shouldIncludeAsCandidate(ApplicationInfo info, UserInfo user) { + if ((info.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0 + || (info.flags & ApplicationInfo.FLAG_SYSTEM) == 0) { + return true; + } + final Intent launchIntent = new Intent(LAUNCHER_PROBE) + .setPackage(info.packageName); + final List intents = mPackageManager.queryIntentActivitiesAsUser( + launchIntent, + PackageManager.MATCH_DISABLED_COMPONENTS + | PackageManager.MATCH_DIRECT_BOOT_AWARE + | PackageManager.MATCH_DIRECT_BOOT_UNAWARE, + user.id); + return intents != null && intents.size() != 0; + } + @Override protected void onDiscardResult(List result) { diff --git a/tests/robotests/src/com/android/settings/search2/InstalledAppResultLoaderTest.java b/tests/robotests/src/com/android/settings/search2/InstalledAppResultLoaderTest.java index 8fde73d88db..4f62a9ece5b 100644 --- a/tests/robotests/src/com/android/settings/search2/InstalledAppResultLoaderTest.java +++ b/tests/robotests/src/com/android/settings/search2/InstalledAppResultLoaderTest.java @@ -17,6 +17,8 @@ package com.android.settings.search2; import android.content.Context; +import android.content.Intent; +import android.content.pm.ResolveInfo; import android.content.pm.UserInfo; import android.os.UserManager; @@ -38,8 +40,11 @@ import java.util.Arrays; import java.util.List; import static android.content.pm.ApplicationInfo.FLAG_SYSTEM; +import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; import static com.google.common.truth.Truth.assertThat; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @RunWith(SettingsRobolectricTestRunner.class) @@ -94,6 +99,55 @@ public class InstalledAppResultLoaderTest { assertThat(mLoader.loadInBackground().size()).isEqualTo(2); } + @Test + public void query_matchingQuery_shouldReturnSystemAppUpdates() { + when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) + .thenReturn(Arrays.asList( + ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_UPDATED_SYSTEM_APP, + 0 /* targetSdkVersion */))); + final String query = "app"; + + mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query); + + assertThat(mLoader.loadInBackground().size()).isEqualTo(1); + } + + @Test + public void query_matchingQuery_shouldReturnSystemAppIfLaunchable() { + when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) + .thenReturn(Arrays.asList( + ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM, + 0 /* targetSdkVersion */))); + final List list = mock(List.class); + when(list.size()).thenReturn(1); + when(mPackageManagerWrapper.queryIntentActivitiesAsUser( + any(Intent.class), anyInt(), anyInt())) + .thenReturn(list); + + final String query = "app"; + + mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query); + + assertThat(mLoader.loadInBackground().size()).isEqualTo(1); + } + + @Test + public void query_matchingQuery_shouldNOtReturnSystemAppIfNotLaunchable() { + when(mPackageManagerWrapper.getInstalledApplicationsAsUser(anyInt(), anyInt())) + .thenReturn(Arrays.asList( + ApplicationTestUtils.buildInfo(0 /* uid */, "app1", FLAG_SYSTEM, + 0 /* targetSdkVersion */))); + when(mPackageManagerWrapper.queryIntentActivitiesAsUser( + any(Intent.class), anyInt(), anyInt())) + .thenReturn(null); + + final String query = "app"; + + mLoader = new InstalledAppResultLoader(mContext, mPackageManagerWrapper, query); + + assertThat(mLoader.loadInBackground()).isEmpty(); + } + @Test public void query_matchingQuery_shouldRankBasedOnSimilarity() { final String query = "app";