Address all lint issues in androidx.core.os classes, including VFY
Relnote: Updated nullability for androidx.core.os classes
Fixes: 206113622
Test: MessageCompatTest, LocaleListCompatTest
Merged-In: If18cd2bcd8b5de33a5e47997339d32e9a13bc312
Change-Id: If18cd2bcd8b5de33a5e47997339d32e9a13bc312
diff --git a/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/IoSettingsActivity.kt b/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/IoSettingsActivity.kt
index b652055..17e5427 100644
--- a/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/IoSettingsActivity.kt
+++ b/compose/integration-tests/macrobenchmark-target/src/main/java/androidx/compose/integration/macrobenchmark/target/IoSettingsActivity.kt
@@ -150,7 +150,7 @@
) {
Text(
text = stringResource(R.string.io_about_title).uppercase(
- LocaleListCompat.getDefault().get(0)
+ LocaleListCompat.getDefault().get(0)!!
),
style = MaterialTheme.typography.body2,
fontWeight = FontWeight.SemiBold,
diff --git a/core/core/api/current.txt b/core/core/api/current.txt
index 4bed9ff..a8121dd 100644
--- a/core/core/api/current.txt
+++ b/core/core/api/current.txt
@@ -1725,12 +1725,12 @@
public final class LocaleListCompat {
method public static androidx.core.os.LocaleListCompat create(java.util.Locale!...);
method public static androidx.core.os.LocaleListCompat forLanguageTags(String?);
- method public java.util.Locale! get(int);
+ method public java.util.Locale? get(int);
method @Size(min=1) public static androidx.core.os.LocaleListCompat getAdjustedDefault();
method @Size(min=1) public static androidx.core.os.LocaleListCompat getDefault();
method public static androidx.core.os.LocaleListCompat getEmptyLocaleList();
method public java.util.Locale? getFirstMatch(String![]);
- method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale!);
+ method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale?);
method public boolean isEmpty();
method @IntRange(from=0) public int size();
method public String toLanguageTags();
diff --git a/core/core/api/public_plus_experimental_current.txt b/core/core/api/public_plus_experimental_current.txt
index 8554f3b..044adaf 100644
--- a/core/core/api/public_plus_experimental_current.txt
+++ b/core/core/api/public_plus_experimental_current.txt
@@ -1730,12 +1730,12 @@
public final class LocaleListCompat {
method public static androidx.core.os.LocaleListCompat create(java.util.Locale!...);
method public static androidx.core.os.LocaleListCompat forLanguageTags(String?);
- method public java.util.Locale! get(int);
+ method public java.util.Locale? get(int);
method @Size(min=1) public static androidx.core.os.LocaleListCompat getAdjustedDefault();
method @Size(min=1) public static androidx.core.os.LocaleListCompat getDefault();
method public static androidx.core.os.LocaleListCompat getEmptyLocaleList();
method public java.util.Locale? getFirstMatch(String![]);
- method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale!);
+ method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale?);
method public boolean isEmpty();
method @IntRange(from=0) public int size();
method public String toLanguageTags();
diff --git a/core/core/api/restricted_current.txt b/core/core/api/restricted_current.txt
index d008d07..99839e8 100644
--- a/core/core/api/restricted_current.txt
+++ b/core/core/api/restricted_current.txt
@@ -2059,12 +2059,12 @@
public final class LocaleListCompat {
method public static androidx.core.os.LocaleListCompat create(java.util.Locale!...);
method public static androidx.core.os.LocaleListCompat forLanguageTags(String?);
- method public java.util.Locale! get(int);
+ method public java.util.Locale? get(int);
method @Size(min=1) public static androidx.core.os.LocaleListCompat getAdjustedDefault();
method @Size(min=1) public static androidx.core.os.LocaleListCompat getDefault();
method public static androidx.core.os.LocaleListCompat getEmptyLocaleList();
method public java.util.Locale? getFirstMatch(String![]);
- method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale!);
+ method @IntRange(from=0xffffffff) public int indexOf(java.util.Locale?);
method public boolean isEmpty();
method @IntRange(from=0) public int size();
method public String toLanguageTags();
diff --git a/core/core/src/main/java/androidx/core/os/CancellationSignal.java b/core/core/src/main/java/androidx/core/os/CancellationSignal.java
index e1b1fed..80e7c1b0 100644
--- a/core/core/src/main/java/androidx/core/os/CancellationSignal.java
+++ b/core/core/src/main/java/androidx/core/os/CancellationSignal.java
@@ -18,7 +18,9 @@
import android.os.Build;
+import androidx.annotation.DoNotInline;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
/**
* Static library support version of the framework's {@link android.os.CancellationSignal}.
@@ -81,7 +83,7 @@
listener.onCancel();
}
if (obj != null && Build.VERSION.SDK_INT >= 16) {
- ((android.os.CancellationSignal) obj).cancel();
+ Api16Impl.cancel(obj);
}
} finally {
synchronized (this) {
@@ -126,7 +128,7 @@
* Gets the framework {@link android.os.CancellationSignal} associated with this object.
* <p>
* Framework support for cancellation signals was added in
- * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} so this method will always
+ * {@link Build.VERSION_CODES#JELLY_BEAN} so this method will always
* return null on older versions of the platform.
* </p>
*
@@ -140,9 +142,9 @@
}
synchronized (this) {
if (mCancellationSignalObj == null) {
- mCancellationSignalObj = new android.os.CancellationSignal();
+ mCancellationSignalObj = Api16Impl.createCancellationSignal();
if (mIsCanceled) {
- ((android.os.CancellationSignal) mCancellationSignalObj).cancel();
+ Api16Impl.cancel(mCancellationSignalObj);
}
}
return mCancellationSignalObj;
@@ -154,6 +156,7 @@
try {
wait();
} catch (InterruptedException ex) {
+ // Do nothing
}
}
}
@@ -167,4 +170,21 @@
*/
void onCancel();
}
+
+ @RequiresApi(16)
+ static class Api16Impl {
+ private Api16Impl() {
+ // This class is not instantiable.
+ }
+
+ @DoNotInline
+ static void cancel(Object cancellationSignal) {
+ ((android.os.CancellationSignal) cancellationSignal).cancel();
+ }
+
+ @DoNotInline
+ static android.os.CancellationSignal createCancellationSignal() {
+ return new android.os.CancellationSignal();
+ }
+ }
}
diff --git a/core/core/src/main/java/androidx/core/os/ConfigurationCompat.java b/core/core/src/main/java/androidx/core/os/ConfigurationCompat.java
index e6b4617..ba35171 100644
--- a/core/core/src/main/java/androidx/core/os/ConfigurationCompat.java
+++ b/core/core/src/main/java/androidx/core/os/ConfigurationCompat.java
@@ -20,7 +20,9 @@
import android.content.res.Configuration;
+import androidx.annotation.DoNotInline;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
/**
* Helper class which allows access to properties of {@link Configuration} in
@@ -39,9 +41,21 @@
@NonNull
public static LocaleListCompat getLocales(@NonNull Configuration configuration) {
if (SDK_INT >= 24) {
- return LocaleListCompat.wrap(configuration.getLocales());
+ return LocaleListCompat.wrap(Api24Impl.getLocales(configuration));
} else {
return LocaleListCompat.create(configuration.locale);
}
}
+
+ @RequiresApi(24)
+ static class Api24Impl {
+ private Api24Impl() {
+ // This class is not instantiable.
+ }
+
+ @DoNotInline
+ static android.os.LocaleList getLocales(Configuration configuration) {
+ return configuration.getLocales();
+ }
+ }
}
diff --git a/core/core/src/main/java/androidx/core/os/EnvironmentCompat.java b/core/core/src/main/java/androidx/core/os/EnvironmentCompat.java
index da61db8..78d1f2a 100644
--- a/core/core/src/main/java/androidx/core/os/EnvironmentCompat.java
+++ b/core/core/src/main/java/androidx/core/os/EnvironmentCompat.java
@@ -20,7 +20,9 @@
import android.os.Environment;
import android.util.Log;
+import androidx.annotation.DoNotInline;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
import java.io.File;
import java.io.IOException;
@@ -57,9 +59,9 @@
@NonNull
public static String getStorageState(@NonNull File path) {
if (Build.VERSION.SDK_INT >= 21) {
- return Environment.getExternalStorageState(path);
+ return Api21Impl.getExternalStorageState(path);
} else if (Build.VERSION.SDK_INT >= 19) {
- return Environment.getStorageState(path);
+ return Api19Impl.getStorageState(path);
}
try {
@@ -78,5 +80,30 @@
return MEDIA_UNKNOWN;
}
- private EnvironmentCompat() {}
+ private EnvironmentCompat() {
+ }
+
+ @RequiresApi(21)
+ static class Api21Impl {
+ private Api21Impl() {
+ // This class is not instantiable.
+ }
+
+ @DoNotInline
+ static String getExternalStorageState(File path) {
+ return Environment.getExternalStorageState(path);
+ }
+ }
+
+ @RequiresApi(19)
+ static class Api19Impl {
+ private Api19Impl() {
+ // This class is not instantiable.
+ }
+
+ @DoNotInline
+ static String getStorageState(File path) {
+ return Environment.getStorageState(path);
+ }
+ }
}
diff --git a/core/core/src/main/java/androidx/core/os/LocaleListCompat.java b/core/core/src/main/java/androidx/core/os/LocaleListCompat.java
index 676b714..a09c8bf 100644
--- a/core/core/src/main/java/androidx/core/os/LocaleListCompat.java
+++ b/core/core/src/main/java/androidx/core/os/LocaleListCompat.java
@@ -19,6 +19,7 @@
import android.os.Build;
import android.os.LocaleList;
+import androidx.annotation.DoNotInline;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -33,7 +34,7 @@
public final class LocaleListCompat {
private static final LocaleListCompat sEmptyLocaleList = create();
- private LocaleListInterface mImpl;
+ private final LocaleListInterface mImpl;
private LocaleListCompat(LocaleListInterface impl) {
mImpl = impl;
@@ -71,7 +72,7 @@
@NonNull
public static LocaleListCompat create(@NonNull Locale... localeList) {
if (Build.VERSION.SDK_INT >= 24) {
- return wrap(new LocaleList(localeList));
+ return wrap(Api24Impl.createLocaleList(localeList));
}
return new LocaleListCompat(new LocaleListCompatWrapper(localeList));
}
@@ -82,6 +83,7 @@
* @param index The position to retrieve.
* @return The {@link Locale} in the given index
*/
+ @Nullable
public Locale get(int index) {
return mImpl.get(index);
}
@@ -113,7 +115,7 @@
* wasn't found
*/
@IntRange(from = -1)
- public int indexOf(Locale locale) {
+ public int indexOf(@Nullable Locale locale) {
return mImpl.indexOf(locale);
}
@@ -162,7 +164,7 @@
final Locale[] localeArray = new Locale[tags.length];
for (int i = 0; i < localeArray.length; i++) {
localeArray[i] = Build.VERSION.SDK_INT >= 21
- ? Locale.forLanguageTag(tags[i])
+ ? Api21Impl.forLanguageTag(tags[i])
: forLanguageTagCompat(tags[i]);
}
return create(localeArray);
@@ -203,7 +205,7 @@
@NonNull @Size(min = 1)
public static LocaleListCompat getAdjustedDefault() {
if (Build.VERSION.SDK_INT >= 24) {
- return LocaleListCompat.wrap(LocaleList.getAdjustedDefault());
+ return LocaleListCompat.wrap(Api24Impl.getAdjustedDefault());
} else {
return LocaleListCompat.create(Locale.getDefault());
}
@@ -223,7 +225,7 @@
@NonNull @Size(min = 1)
public static LocaleListCompat getDefault() {
if (Build.VERSION.SDK_INT >= 24) {
- return LocaleListCompat.wrap(LocaleList.getDefault());
+ return LocaleListCompat.wrap(Api24Impl.getDefault());
} else {
return LocaleListCompat.create(Locale.getDefault());
}
@@ -239,8 +241,43 @@
return mImpl.hashCode();
}
+ @NonNull
@Override
public String toString() {
return mImpl.toString();
}
+
+ @RequiresApi(24)
+ static class Api24Impl {
+ private Api24Impl() {
+ // This class is not instantiable.
+ }
+
+ @DoNotInline
+ static LocaleList createLocaleList(Locale... list) {
+ return new LocaleList(list);
+ }
+
+ @DoNotInline
+ static LocaleList getAdjustedDefault() {
+ return LocaleList.getAdjustedDefault();
+ }
+
+ @DoNotInline
+ static LocaleList getDefault() {
+ return LocaleList.getDefault();
+ }
+ }
+
+ @RequiresApi(21)
+ static class Api21Impl {
+ private Api21Impl() {
+ // This class is not instantiable.
+ }
+
+ @DoNotInline
+ static Locale forLanguageTag(String languageTag) {
+ return Locale.forLanguageTag(languageTag);
+ }
+ }
}
diff --git a/core/core/src/main/java/androidx/core/os/LocaleListCompatWrapper.java b/core/core/src/main/java/androidx/core/os/LocaleListCompatWrapper.java
index db9306a..94ebde2 100644
--- a/core/core/src/main/java/androidx/core/os/LocaleListCompatWrapper.java
+++ b/core/core/src/main/java/androidx/core/os/LocaleListCompatWrapper.java
@@ -18,9 +18,11 @@
import android.os.Build;
+import androidx.annotation.DoNotInline;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import java.util.ArrayList;
@@ -94,12 +96,13 @@
@Override
public int hashCode() {
int result = 1;
- for (int i = 0; i < mList.length; i++) {
- result = 31 * result + mList[i].hashCode();
+ for (Locale locale : mList) {
+ result = 31 * result + locale.hashCode();
}
return result;
}
+ @NonNull
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -125,15 +128,13 @@
mStringRepresentation = "";
} else {
final List<Locale> localeList = new ArrayList<>();
- final HashSet<Locale> seenLocales = new HashSet<Locale>();
+ final HashSet<Locale> seenLocales = new HashSet<>();
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < list.length; i++) {
final Locale l = list[i];
if (l == null) {
throw new NullPointerException("list[" + i + "] is null");
- } else if (seenLocales.contains(l)) {
- // Ignore repeated locale
- } else {
+ } else if (!seenLocales.contains(l)) {
final Locale localeClone = (Locale) l.clone();
localeList.add(localeClone);
toLanguageTag(sb, localeClone);
@@ -143,7 +144,7 @@
seenLocales.add(localeClone);
}
}
- mList = localeList.toArray(new Locale[localeList.size()]);
+ mList = localeList.toArray(new Locale[0]);
mStringRepresentation = sb.toString();
}
}
@@ -152,6 +153,8 @@
static void toLanguageTag(StringBuilder builder, Locale locale) {
builder.append(locale.getLanguage());
final String country = locale.getCountry();
+ // No guarantee that getCountry() was non-null in earlier SDKs.
+ //noinspection ConstantConditions
if (country != null && !country.isEmpty()) {
builder.append('-');
builder.append(locale.getCountry());
@@ -160,7 +163,7 @@
private static String getLikelyScript(Locale locale) {
if (Build.VERSION.SDK_INT >= 21) {
- final String script = locale.getScript();
+ final String script = Api21Impl.getScript(locale);
if (!script.isEmpty()) {
return script;
} else {
@@ -267,4 +270,16 @@
return computeFirstMatch(Arrays.asList(supportedLocales),
false /* assume English is not supported */);
}
+
+ @RequiresApi(21)
+ static class Api21Impl {
+ private Api21Impl() {
+ // This class is not instantiable.
+ }
+
+ @DoNotInline
+ static String getScript(Locale locale) {
+ return locale.getScript();
+ }
+ }
}
diff --git a/core/core/src/main/java/androidx/core/os/LocaleListPlatformWrapper.java b/core/core/src/main/java/androidx/core/os/LocaleListPlatformWrapper.java
index 3968e0f..0d96663 100644
--- a/core/core/src/main/java/androidx/core/os/LocaleListPlatformWrapper.java
+++ b/core/core/src/main/java/androidx/core/os/LocaleListPlatformWrapper.java
@@ -28,8 +28,8 @@
final class LocaleListPlatformWrapper implements LocaleListInterface {
private final LocaleList mLocaleList;
- LocaleListPlatformWrapper(LocaleList localeList) {
- mLocaleList = localeList;
+ LocaleListPlatformWrapper(Object localeList) {
+ mLocaleList = (LocaleList) localeList;
}
@Override
diff --git a/core/core/src/main/java/androidx/core/os/MessageCompat.java b/core/core/src/main/java/androidx/core/os/MessageCompat.java
index a278c0756..7340ab2 100644
--- a/core/core/src/main/java/androidx/core/os/MessageCompat.java
+++ b/core/core/src/main/java/androidx/core/os/MessageCompat.java
@@ -20,8 +20,11 @@
import android.os.Build;
import android.os.Looper;
import android.os.Message;
+import android.view.View;
+import androidx.annotation.DoNotInline;
import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
/**
* Helper for accessing features in {@link Message}.
@@ -45,7 +48,7 @@
* Certain operations, such as view invalidation, may introduce synchronization
* barriers into the {@link Looper}'s message queue to prevent subsequent messages
* from being delivered until some condition is met. In the case of view invalidation,
- * messages which are posted after a call to {@link android.view.View#invalidate}
+ * messages which are posted after a call to {@link View#invalidate}
* are suspended by means of a synchronization barrier until the next frame is
* ready to be drawn. The synchronization barrier ensures that the invalidation
* request is completely handled before resuming.
@@ -69,14 +72,14 @@
@SuppressLint("NewApi")
public static void setAsynchronous(@NonNull Message message, boolean async) {
if (Build.VERSION.SDK_INT >= 22) {
- message.setAsynchronous(async);
+ Api22Impl.setAsynchronous(message, async);
return;
}
if (sTrySetAsynchronous && Build.VERSION.SDK_INT >= 16) {
// Since this was an @hide method made public, we can link directly against it with a
// try/catch for its absence instead of doing the same dance through reflection.
try {
- message.setAsynchronous(async);
+ Api22Impl.setAsynchronous(message, async);
} catch (NoSuchMethodError e) {
sTrySetAsynchronous = false;
}
@@ -95,13 +98,13 @@
@SuppressLint("NewApi")
public static boolean isAsynchronous(@NonNull Message message) {
if (Build.VERSION.SDK_INT >= 22) {
- return message.isAsynchronous();
+ return Api22Impl.isAsynchronous(message);
}
if (sTryIsAsynchronous && Build.VERSION.SDK_INT >= 16) {
// Since this was an @hide method made public, we can link directly against it with a
// try/catch for its absence instead of doing the same dance through reflection.
try {
- return message.isAsynchronous();
+ return Api22Impl.isAsynchronous(message);
} catch (NoSuchMethodError e) {
sTryIsAsynchronous = false;
}
@@ -111,4 +114,21 @@
private MessageCompat() {
}
+
+ @RequiresApi(22)
+ static class Api22Impl {
+ private Api22Impl() {
+ // This class is not instantiable.
+ }
+
+ @DoNotInline
+ static boolean isAsynchronous(Message message) {
+ return message.isAsynchronous();
+ }
+
+ @DoNotInline
+ static void setAsynchronous(Message message, boolean async) {
+ message.setAsynchronous(async);
+ }
+ }
}