Fix errorprone warnings that should be errors
This commit is part of a large scale change to fix errorprone errors that have been downgraded to warnings in the android source tree, so that they can be promoted to errors again. The full list of changes include the following, but not all will be present in any one individual commit: BadAnnotationImplementation BadShiftAmount BanJNDI BoxedPrimitiveEquality ComparableType ComplexBooleanConstant CollectionToArraySafeParameter ConditionalExpressionNumericPromotion DangerousLiteralNull DoubleBraceInitialization DurationFrom DurationTemporalUnit EmptyTopLevelDeclaration EqualsNull EqualsReference FormatString FromTemporalAccessor GetClassOnAnnotation GetClassOnClass HashtableContains IdentityBinaryExpression IdentityHashMapBoxing InstantTemporalUnit InvalidTimeZoneID InvalidZoneId IsInstanceIncompatibleType JUnitParameterMethodNotFound LockOnBoxedPrimitive MathRoundIntLong MislabeledAndroidString MisusedDayOfYear MissingSuperCall MisusedWeekYear ModifyingCollectionWithItself NoCanIgnoreReturnValueOnClasses NonRuntimeAnnotation NullableOnContainingClass NullTernary OverridesJavaxInjectableMethod ParcelableCreator PeriodFrom PreconditionsInvalidPlaceholder ProtoBuilderReturnValueIgnored ProtoFieldNullComparison RandomModInteger RectIntersectReturnValueIgnored ReturnValueIgnored SelfAssignment SelfComparison SelfEquals SizeGreaterThanOrEqualsZero StringBuilderInitWithChar TreeToString TryFailThrowable UnnecessaryCheckNotNull UnusedCollectionModifiedInPlace XorPower See https://errorprone.info/bugpatterns for more information on the checks. Bug: 253827323 Test: m RUN_ERROR_PRONE=true javac-check Change-Id: I29f691a22617b1fc834680ff1cf4ab4244203f06
This commit is contained in:
@@ -171,8 +171,8 @@ class TrustedCredentialsDialogBuilder extends AlertDialog.Builder {
|
||||
} else {
|
||||
new AlertDialog.Builder(mActivity)
|
||||
.setMessage(R.string.trusted_credentials_remove_confirmation)
|
||||
.setPositiveButton(android.R.string.yes, onConfirm)
|
||||
.setNegativeButton(android.R.string.no, null)
|
||||
.setPositiveButton(android.R.string.ok, onConfirm)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
|
||||
}
|
||||
|
@@ -123,6 +123,7 @@ public class AccountDashboardFragment extends DashboardFragment {
|
||||
return controllers;
|
||||
}
|
||||
|
||||
@SuppressWarnings("MissingSuperCall") // TODO: Fix me
|
||||
@Override
|
||||
public List<SearchIndexableRaw> getDynamicRawDataToIndex(Context context,
|
||||
boolean enabled) {
|
||||
|
@@ -31,7 +31,7 @@ import java.util.stream.Collectors;
|
||||
* A buffer of the supported link data. This {@link SupportedLinkWrapper} wraps the host, enabled
|
||||
* and a list of {@link DomainOwner}.
|
||||
*/
|
||||
public class SupportedLinkWrapper implements Comparable {
|
||||
public class SupportedLinkWrapper implements Comparable<SupportedLinkWrapper> {
|
||||
private static final String TAG = "SupportedLinkWrapper";
|
||||
|
||||
private String mHost;
|
||||
@@ -112,8 +112,7 @@ public class SupportedLinkWrapper implements Comparable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object o) {
|
||||
final SupportedLinkWrapper that = (SupportedLinkWrapper) o;
|
||||
public int compareTo(SupportedLinkWrapper that) {
|
||||
if (this.mIsEnabled != that.mIsEnabled) {
|
||||
return this.mIsEnabled ? -1 : 1;
|
||||
}
|
||||
|
@@ -713,6 +713,7 @@ public class FingerprintEnrollEnrolling extends BiometricsEnrollEnrolling {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("MissingSuperCall") // TODO: Fix me
|
||||
@Override
|
||||
public void onConfigurationChanged(@NonNull Configuration newConfig) {
|
||||
switch(newConfig.orientation) {
|
||||
|
@@ -57,8 +57,8 @@ public class DisableLogPersistWarningDialog extends InstrumentedDialogFragment i
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.dev_logpersist_clear_warning_title)
|
||||
.setMessage(R.string.dev_logpersist_clear_warning_message)
|
||||
.setPositiveButton(android.R.string.yes, this /* onClickListener */)
|
||||
.setNegativeButton(android.R.string.no, this /* onClickListener */)
|
||||
.setPositiveButton(android.R.string.ok, this /* onClickListener */)
|
||||
.setNegativeButton(android.R.string.cancel, this /* onClickListener */)
|
||||
.create();
|
||||
}
|
||||
|
||||
|
@@ -52,8 +52,8 @@ public class EnableAdbWarningDialog extends InstrumentedDialogFragment implement
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.adb_warning_title)
|
||||
.setMessage(R.string.adb_warning_message)
|
||||
.setPositiveButton(android.R.string.yes, this /* onClickListener */)
|
||||
.setNegativeButton(android.R.string.no, this /* onClickListener */)
|
||||
.setPositiveButton(android.R.string.ok, this /* onClickListener */)
|
||||
.setNegativeButton(android.R.string.cancel, this /* onClickListener */)
|
||||
.create();
|
||||
}
|
||||
|
||||
|
@@ -53,8 +53,8 @@ public class EnableDevelopmentSettingWarningDialog extends InstrumentedDialogFra
|
||||
return new AlertDialog.Builder(getActivity())
|
||||
.setMessage(R.string.dev_settings_warning_message)
|
||||
.setTitle(R.string.dev_settings_warning_title)
|
||||
.setPositiveButton(android.R.string.yes, this)
|
||||
.setNegativeButton(android.R.string.no, this)
|
||||
.setPositiveButton(android.R.string.ok, this)
|
||||
.setNegativeButton(android.R.string.cancel, this)
|
||||
.create();
|
||||
}
|
||||
|
||||
|
@@ -34,7 +34,6 @@ import com.android.settings.homepage.contextualcards.slices.SliceContextualCardR
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ContextualCardLookupTable {
|
||||
@@ -65,41 +64,39 @@ public class ContextualCardLookupTable {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static final Set<ControllerRendererMapping> LOOKUP_TABLE =
|
||||
new TreeSet<ControllerRendererMapping>() {{
|
||||
add(new ControllerRendererMapping(CardType.CONDITIONAL,
|
||||
static final Set<ControllerRendererMapping> LOOKUP_TABLE = Set.of(
|
||||
new ControllerRendererMapping(CardType.CONDITIONAL,
|
||||
ConditionContextualCardRenderer.VIEW_TYPE_HALF_WIDTH,
|
||||
ConditionContextualCardController.class,
|
||||
ConditionContextualCardRenderer.class));
|
||||
add(new ControllerRendererMapping(CardType.CONDITIONAL,
|
||||
ConditionContextualCardRenderer.class),
|
||||
new ControllerRendererMapping(CardType.CONDITIONAL,
|
||||
ConditionContextualCardRenderer.VIEW_TYPE_FULL_WIDTH,
|
||||
ConditionContextualCardController.class,
|
||||
ConditionContextualCardRenderer.class));
|
||||
add(new ControllerRendererMapping(CardType.LEGACY_SUGGESTION,
|
||||
ConditionContextualCardRenderer.class),
|
||||
new ControllerRendererMapping(CardType.LEGACY_SUGGESTION,
|
||||
LegacySuggestionContextualCardRenderer.VIEW_TYPE,
|
||||
LegacySuggestionContextualCardController.class,
|
||||
LegacySuggestionContextualCardRenderer.class));
|
||||
add(new ControllerRendererMapping(CardType.SLICE,
|
||||
LegacySuggestionContextualCardRenderer.class),
|
||||
new ControllerRendererMapping(CardType.SLICE,
|
||||
SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH,
|
||||
SliceContextualCardController.class,
|
||||
SliceContextualCardRenderer.class));
|
||||
add(new ControllerRendererMapping(CardType.SLICE,
|
||||
SliceContextualCardRenderer.class),
|
||||
new ControllerRendererMapping(CardType.SLICE,
|
||||
SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH,
|
||||
SliceContextualCardController.class,
|
||||
SliceContextualCardRenderer.class));
|
||||
add(new ControllerRendererMapping(CardType.SLICE,
|
||||
SliceContextualCardRenderer.class),
|
||||
new ControllerRendererMapping(CardType.SLICE,
|
||||
SliceContextualCardRenderer.VIEW_TYPE_STICKY,
|
||||
SliceContextualCardController.class,
|
||||
SliceContextualCardRenderer.class));
|
||||
add(new ControllerRendererMapping(CardType.CONDITIONAL_FOOTER,
|
||||
SliceContextualCardRenderer.class),
|
||||
new ControllerRendererMapping(CardType.CONDITIONAL_FOOTER,
|
||||
ConditionFooterContextualCardRenderer.VIEW_TYPE,
|
||||
ConditionContextualCardController.class,
|
||||
ConditionFooterContextualCardRenderer.class));
|
||||
add(new ControllerRendererMapping(CardType.CONDITIONAL_HEADER,
|
||||
ConditionFooterContextualCardRenderer.class),
|
||||
new ControllerRendererMapping(CardType.CONDITIONAL_HEADER,
|
||||
ConditionHeaderContextualCardRenderer.VIEW_TYPE,
|
||||
ConditionContextualCardController.class,
|
||||
ConditionHeaderContextualCardRenderer.class));
|
||||
}};
|
||||
|
||||
public static Class<? extends ContextualCardController> getCardControllerClass(
|
||||
@CardType int cardType) {
|
||||
|
@@ -55,7 +55,6 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -196,11 +195,10 @@ public class ContextualCardManager implements ContextualCardLoader.CardContentLo
|
||||
// except Conditional cards, all other cards are from the database. So when the map sent
|
||||
// here is empty, we only keep Conditional cards.
|
||||
if (cardTypes.isEmpty()) {
|
||||
final Set<Integer> conditionalCardTypes = new TreeSet<Integer>() {{
|
||||
add(ContextualCard.CardType.CONDITIONAL);
|
||||
add(ContextualCard.CardType.CONDITIONAL_HEADER);
|
||||
add(ContextualCard.CardType.CONDITIONAL_FOOTER);
|
||||
}};
|
||||
final Set<Integer> conditionalCardTypes = Set.of(
|
||||
ContextualCard.CardType.CONDITIONAL,
|
||||
ContextualCard.CardType.CONDITIONAL_HEADER,
|
||||
ContextualCard.CardType.CONDITIONAL_FOOTER);
|
||||
cardsToKeep = mContextualCards.stream()
|
||||
.filter(card -> conditionalCardTypes.contains(card.getCardType()))
|
||||
.collect(Collectors.toList());
|
||||
|
@@ -202,7 +202,7 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
|
||||
new AlertDialog.Builder(getActivity())
|
||||
.setTitle(R.string.dlg_remove_locales_error_title)
|
||||
.setMessage(R.string.dlg_remove_locales_error_message)
|
||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
}
|
||||
@@ -228,7 +228,7 @@ public class LocaleListEditor extends RestrictedSettingsFragment {
|
||||
}
|
||||
|
||||
builder.setTitle(title)
|
||||
.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
|
||||
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
setRemoveMode(false);
|
||||
|
@@ -35,7 +35,7 @@ public class TetherProvisioningCarrierDialogActivity extends Activity {
|
||||
.setTitle(R.string.wifi_tether_carrier_unsupport_dialog_title)
|
||||
.setMessage(R.string.wifi_tether_carrier_unsupport_dialog_content)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dialog.cancel();
|
||||
finish();
|
||||
|
@@ -568,7 +568,7 @@ public class ApnEditor extends SettingsPreferenceFragment
|
||||
// Network code
|
||||
final String mnc = (subInfo == null) ? null : subInfo.getMncString();
|
||||
|
||||
if ((!TextUtils.isEmpty(mcc)) && (!TextUtils.isEmpty(mcc))) {
|
||||
if (!TextUtils.isEmpty(mcc)) {
|
||||
// Auto populate MNC and MCC for new entries, based on what SIM reports
|
||||
mMcc.setText(mcc);
|
||||
mMnc.setText(mnc);
|
||||
|
@@ -70,8 +70,8 @@ public class RoamingDialogFragment extends InstrumentedDialogFragment implements
|
||||
builder.setMessage(getResources().getString(message))
|
||||
.setTitle(title)
|
||||
.setIconAttribute(android.R.attr.alertDialogIcon)
|
||||
.setPositiveButton(android.R.string.yes, this)
|
||||
.setNegativeButton(android.R.string.no, this);
|
||||
.setPositiveButton(android.R.string.ok, this)
|
||||
.setNegativeButton(android.R.string.cancel, this);
|
||||
AlertDialog dialog = builder.create();
|
||||
dialog.setCanceledOnTouchOutside(false);
|
||||
return dialog;
|
||||
|
@@ -363,7 +363,7 @@ public class SoundWorkSettingsController extends AbstractPreferenceController
|
||||
() -> context.getString(R.string.work_sync_dialog_message)))
|
||||
.setPositiveButton(R.string.work_sync_dialog_yes,
|
||||
SoundWorkSettingsController.UnifyWorkDialogFragment.this)
|
||||
.setNegativeButton(android.R.string.no, /* listener= */ null)
|
||||
.setNegativeButton(android.R.string.cancel, /* listener= */ null)
|
||||
.create();
|
||||
}
|
||||
|
||||
|
@@ -10,7 +10,7 @@ import java.util.Objects;
|
||||
* Holds packageName:userId pairs without any heavyweight fields.
|
||||
* {@see ApplicationInfo}
|
||||
*/
|
||||
class AppVpnInfo implements Comparable {
|
||||
class AppVpnInfo implements Comparable<AppVpnInfo> {
|
||||
public final int userId;
|
||||
public final String packageName;
|
||||
|
||||
@@ -20,12 +20,10 @@ class AppVpnInfo implements Comparable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Object other) {
|
||||
AppVpnInfo that = (AppVpnInfo) other;
|
||||
|
||||
int result = packageName.compareTo(that.packageName);
|
||||
public int compareTo(AppVpnInfo other) {
|
||||
int result = packageName.compareTo(other.packageName);
|
||||
if (result == 0) {
|
||||
result = that.userId - userId;
|
||||
result = other.userId - userId;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@@ -117,6 +117,7 @@ public class WifiDialog extends AlertDialog implements WifiConfigUiBase,
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("MissingSuperCall") // TODO: Fix me
|
||||
@Override
|
||||
protected void onStart() {
|
||||
final ImageButton ssidScannerButton = findViewById(R.id.ssid_scanner_button);
|
||||
|
@@ -137,6 +137,7 @@ public class WifiDialog2 extends AlertDialog implements WifiConfigUiBase2,
|
||||
window.setAttributes(lp);
|
||||
}
|
||||
|
||||
@SuppressWarnings("MissingSuperCall") // TODO: Fix me
|
||||
@Override
|
||||
protected void onStart() {
|
||||
final ImageButton ssidScannerButton = findViewById(R.id.ssid_scanner_button);
|
||||
|
@@ -405,6 +405,7 @@ public class ToggleFeaturePreferenceFragmentTest {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@SuppressWarnings("MissingSuperCall")
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
// do nothing
|
||||
|
@@ -473,6 +473,7 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
@SuppressWarnings("MissingSuperCall")
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
// do nothing
|
||||
|
@@ -50,6 +50,7 @@ public class AppFilterItemTest {
|
||||
assertThat(item).isEqualTo(item2);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SelfComparison")
|
||||
@Test
|
||||
public void compare_sameContent_return0() {
|
||||
final AppFilterItem item = AppFilterRegistry.getInstance().get(FILTER_APPS_USAGE_ACCESS);
|
||||
|
@@ -141,10 +141,9 @@ public class BluetoothSampleRateDialogPreferenceControllerTest {
|
||||
|
||||
@Test
|
||||
public void getSelectableIndex_verifyList() {
|
||||
List<BluetoothCodecConfig> mCodecConfigs = new ArrayList() {{
|
||||
add(mCodecConfigAAC);
|
||||
add(mCodecConfigSBC);
|
||||
}};
|
||||
List<BluetoothCodecConfig> mCodecConfigs = List.of(
|
||||
mCodecConfigAAC,
|
||||
mCodecConfigSBC);
|
||||
mCodecStatus = new BluetoothCodecStatus.Builder()
|
||||
.setCodecConfig(mCodecConfigAAC)
|
||||
.setCodecsSelectableCapabilities(mCodecConfigs)
|
||||
|
@@ -43,16 +43,16 @@ public class ConfirmCredentialTest {
|
||||
|
||||
// Launch only one instance at a time.
|
||||
assertThat(LastTryDialog.show(
|
||||
fm, "title", mContext.getString(android.R.string.yes),
|
||||
fm, "title", mContext.getString(android.R.string.ok),
|
||||
android.R.string.ok, false)).isTrue();
|
||||
assertThat(LastTryDialog.show(
|
||||
fm, "title", mContext.getString(android.R.string.yes),
|
||||
fm, "title", mContext.getString(android.R.string.ok),
|
||||
android.R.string.ok, false)).isFalse();
|
||||
|
||||
// After cancelling, the dialog should be re-shown when asked for.
|
||||
LastTryDialog.hide(fm);
|
||||
assertThat(LastTryDialog.show(
|
||||
fm, "title", mContext.getString(android.R.string.yes),
|
||||
fm, "title", mContext.getString(android.R.string.ok),
|
||||
android.R.string.ok, false)).isTrue();
|
||||
}
|
||||
}
|
||||
|
@@ -29,7 +29,7 @@ import android.test.InstrumentationTestCase;
|
||||
import android.test.suitebuilder.annotation.MediumTest;
|
||||
import android.test.suitebuilder.annotation.Suppress;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SoundSettingsTest extends InstrumentationTestCase {
|
||||
private static final String PAGE = Settings.ACTION_SOUND_SETTINGS;
|
||||
@@ -40,60 +40,54 @@ public class SoundSettingsTest extends InstrumentationTestCase {
|
||||
private SettingsHelper mHelper;
|
||||
|
||||
|
||||
private HashMap ringtoneSounds = new HashMap<String, String>() {{
|
||||
put("angler","Dione");
|
||||
put("bullhead","Dione");
|
||||
put("marlin","Spaceship");
|
||||
put("sailfish","Spaceship");
|
||||
put("walleye","Copycat");
|
||||
put("taimen","Copycat");
|
||||
}};
|
||||
private final Map<String, String> ringtoneSounds = Map.of(
|
||||
"angler", "Dione",
|
||||
"bullhead", "Dione",
|
||||
"marlin", "Spaceship",
|
||||
"sailfish", "Spaceship",
|
||||
"walleye", "Copycat",
|
||||
"taimen", "Copycat");
|
||||
|
||||
private HashMap ringtoneCodes = new HashMap<String, String>() {{
|
||||
put("angler","38");
|
||||
put("bullhead","38");
|
||||
put("marlin","37");
|
||||
put("sailfish","37");
|
||||
put("walleye","26");
|
||||
put("taimen","26");
|
||||
}};
|
||||
private final Map<String, String> ringtoneCodes = Map.of(
|
||||
"angler", "38",
|
||||
"bullhead", "38",
|
||||
"marlin", "37",
|
||||
"sailfish", "37",
|
||||
"walleye", "26",
|
||||
"taimen", "26");
|
||||
|
||||
private HashMap alarmSounds = new HashMap<String, String>() {{
|
||||
put("angler","Awaken");
|
||||
put("bullhead","Awaken");
|
||||
put("marlin","Bounce");
|
||||
put("sailfish","Bounce");
|
||||
put("walleye","Cuckoo clock");
|
||||
put("taimen","Cuckoo clock");
|
||||
}};
|
||||
private final Map<String, String> alarmSounds = Map.of(
|
||||
"angler", "Awaken",
|
||||
"bullhead", "Awaken",
|
||||
"marlin", "Bounce",
|
||||
"sailfish", "Bounce",
|
||||
"walleye", "Cuckoo clock",
|
||||
"taimen", "Cuckoo clock");
|
||||
|
||||
private HashMap alarmCodes = new HashMap<String, String>() {{
|
||||
put("angler","6");
|
||||
put("bullhead","6");
|
||||
put("marlin","49");
|
||||
put("sailfish","49");
|
||||
put("walleye","15");
|
||||
put("taimen","15");
|
||||
}};
|
||||
private final Map<String, String> alarmCodes = Map.of(
|
||||
"angler", "6",
|
||||
"bullhead", "6",
|
||||
"marlin", "49",
|
||||
"sailfish", "49",
|
||||
"walleye", "15",
|
||||
"taimen", "15");
|
||||
|
||||
private HashMap notificationSounds = new HashMap<String, String>() {{
|
||||
put("angler","Ceres");
|
||||
put("bullhead","Ceres");
|
||||
put("marlin","Trill");
|
||||
put("sailfish","Trill");
|
||||
put("walleye","Pipes");
|
||||
put("taimen","Pipes");
|
||||
}};
|
||||
private final Map<String, String> notificationSounds = Map.of(
|
||||
"angler", "Ceres",
|
||||
"bullhead", "Ceres",
|
||||
"marlin", "Trill",
|
||||
"sailfish", "Trill",
|
||||
"walleye", "Pipes",
|
||||
"taimen", "Pipes");
|
||||
|
||||
|
||||
private HashMap notificationCodes = new HashMap<String, String>() {{
|
||||
put("angler","26");
|
||||
put("bullhead","26");
|
||||
put("marlin","57");
|
||||
put("sailfish","57");
|
||||
put("walleye","69");
|
||||
put("taimen","69");
|
||||
}};
|
||||
private final Map<String, String> notificationCodes = Map.of(
|
||||
"angler", "26",
|
||||
"bullhead", "26",
|
||||
"marlin", "57",
|
||||
"sailfish", "57",
|
||||
"walleye", "69",
|
||||
"taimen", "69");
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
|
Reference in New Issue
Block a user