Fixes AOSP crash when WPP isn't installed.

If there is no installed application with the ability to start an
activity with the SET_WALLPAPER action, we no longer show the
"Shortcuts" entry under the "Display > Lock screen" settings page.

Flag: CUSTOMIZABLE_LOCK_SCREEN_QUICK_AFFORDANCES
Fix: 274075866
Test: expanded unit test
Test: manually verified that, if Intent.resolveActivity returns false,
the shortcuts item isn't present in settings.

Change-Id: I919427d1e71a88a520c762307029a53065a68f46
This commit is contained in:
Alejandro Nijamkin
2023-03-21 13:57:25 -07:00
parent f0c3812123
commit 20e244a964
3 changed files with 57 additions and 7 deletions

View File

@@ -50,7 +50,7 @@ public class CustomizableLockScreenQuickAffordancesPreferenceController extends
final Preference preference = screen.findPreference(getPreferenceKey()); final Preference preference = screen.findPreference(getPreferenceKey());
if (preference != null) { if (preference != null) {
preference.setOnPreferenceClickListener(preference1 -> { preference.setOnPreferenceClickListener(preference1 -> {
final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER); final Intent intent = CustomizableLockScreenUtils.newIntent();
final String packageName = final String packageName =
mContext.getString(R.string.config_wallpaper_picker_package); mContext.getString(R.string.config_wallpaper_picker_package);
if (!TextUtils.isEmpty(packageName)) { if (!TextUtils.isEmpty(packageName)) {

View File

@@ -18,6 +18,8 @@ package com.android.settings.display;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor; import android.database.Cursor;
import android.net.Uri; import android.net.Uri;
import android.text.TextUtils; import android.text.TextUtils;
@@ -67,6 +69,10 @@ public final class CustomizableLockScreenUtils {
* <p>This is a slow, blocking call that shouldn't be made on the main thread. * <p>This is a slow, blocking call that shouldn't be made on the main thread.
*/ */
public static boolean isFeatureEnabled(Context context) { public static boolean isFeatureEnabled(Context context) {
if (!isWallpaperPickerInstalled(context)) {
return false;
}
try (Cursor cursor = context.getContentResolver().query( try (Cursor cursor = context.getContentResolver().query(
FLAGS_URI, FLAGS_URI,
null, null,
@@ -151,4 +157,17 @@ public final class CustomizableLockScreenUtils {
return null; return null;
} }
} }
/**
* Returns a new {@link Intent} that can be used to start the wallpaper picker
* activity.
*/
public static Intent newIntent() {
return new Intent(Intent.ACTION_SET_WALLPAPER);
}
private static boolean isWallpaperPickerInstalled(Context context) {
final PackageManager packageManager = context.getPackageManager();
return newIntent().resolveActivity(packageManager) != null;
}
} }

View File

@@ -21,6 +21,8 @@ import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
@@ -28,6 +30,10 @@ import static org.mockito.Mockito.when;
import android.content.ContentResolver; import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.database.MatrixCursor; import android.database.MatrixCursor;
import android.text.TextUtils; import android.text.TextUtils;
@@ -54,6 +60,7 @@ public class CustomizableLockScreenQuickAffordancesPreferenceControllerTest {
@Mock private Context mContext; @Mock private Context mContext;
@Mock private ContentResolver mContentResolver; @Mock private ContentResolver mContentResolver;
@Mock private PackageManager mPackageManager;
private CustomizableLockScreenQuickAffordancesPreferenceController mUnderTest; private CustomizableLockScreenQuickAffordancesPreferenceController mUnderTest;
@@ -63,20 +70,28 @@ public class CustomizableLockScreenQuickAffordancesPreferenceControllerTest {
when(mContext.getContentResolver()).thenReturn(mContentResolver); when(mContext.getContentResolver()).thenReturn(mContentResolver);
when(mContext.getResources()) when(mContext.getResources())
.thenReturn(ApplicationProvider.getApplicationContext().getResources()); .thenReturn(ApplicationProvider.getApplicationContext().getResources());
when(mContext.getPackageManager()).thenReturn(mPackageManager);
mUnderTest = new CustomizableLockScreenQuickAffordancesPreferenceController(mContext, KEY); mUnderTest = new CustomizableLockScreenQuickAffordancesPreferenceController(mContext, KEY);
} }
@Test @Test
public void getAvailabilityStatus_whenEnabled() { public void getAvailabilityStatus_whenFeatureEnabled() {
setEnabled(true); setEnabled(/* isWallpaperPickerInstalled= */ true, /* isFeatureEnabled = */ true);
assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(AVAILABLE); assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(AVAILABLE);
} }
@Test @Test
public void getAvailabilityStatus_whenNotEnabled() { public void getAvailabilityStatus_whenWallpaperPickerNotInstalledEnabled() {
setEnabled(false); setEnabled(/* isWallpaperPickerInstalled= */ false, /* isFeatureEnabled = */ true);
assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
@Test
public void getAvailabilityStatus_whenFeatureNotEnabled() {
setEnabled(/* isWallpaperPickerInstalled= */ true, /* isFeatureEnabled = */ false);
assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE); assertThat(mUnderTest.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
} }
@@ -127,13 +142,29 @@ public class CustomizableLockScreenQuickAffordancesPreferenceControllerTest {
assertThat(TextUtils.equals(mUnderTest.getSummary(), "one, two")).isTrue(); assertThat(TextUtils.equals(mUnderTest.getSummary(), "one, two")).isTrue();
} }
private void setEnabled(boolean isEnabled) { private void setEnabled(boolean isWallpaperPickerInstalled, boolean isFeatureEnabled) {
if (isWallpaperPickerInstalled) {
final ResolveInfo resolveInfo = new ResolveInfo();
final ActivityInfo activityInfo = new ActivityInfo();
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.packageName = "com.fake.name";
activityInfo.applicationInfo = applicationInfo;
activityInfo.name = "someName";
resolveInfo.activityInfo = activityInfo;
when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(resolveInfo);
} else {
when(mPackageManager.resolveActivity(any(), anyInt())).thenReturn(null);
}
final MatrixCursor cursor = new MatrixCursor( final MatrixCursor cursor = new MatrixCursor(
new String[] { new String[] {
CustomizableLockScreenUtils.NAME, CustomizableLockScreenUtils.NAME,
CustomizableLockScreenUtils.VALUE CustomizableLockScreenUtils.VALUE
}); });
cursor.addRow(new Object[] { CustomizableLockScreenUtils.ENABLED_FLAG, isEnabled ? 1 : 0 }); cursor.addRow(
new Object[] {
CustomizableLockScreenUtils.ENABLED_FLAG, isFeatureEnabled ? 1 : 0
});
when( when(
mContentResolver.query( mContentResolver.query(
CustomizableLockScreenUtils.FLAGS_URI, null, null, null)) CustomizableLockScreenUtils.FLAGS_URI, null, null, null))