Merge "Fix correctness issues while choosing Adapters for LifecycleObservers" into oc-mr1-support-27.0-dev
diff --git a/app-toolkit/core-testing/src/androidTest/java/android/arch/core/executor/testing/CountingTaskExecutorRuleTest.java b/app-toolkit/core-testing/src/androidTest/java/android/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
index ad36b9b..a6a5b2e 100644
--- a/app-toolkit/core-testing/src/androidTest/java/android/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
+++ b/app-toolkit/core-testing/src/androidTest/java/android/arch/core/executor/testing/CountingTaskExecutorRuleTest.java
@@ -19,7 +19,7 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.support.test.filters.MediumTest;
import android.support.test.runner.AndroidJUnit4;
@@ -115,13 +115,13 @@
private LatchRunnable runOnIO() {
LatchRunnable latchRunnable = new LatchRunnable();
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(latchRunnable);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(latchRunnable);
return latchRunnable;
}
private LatchRunnable runOnMain() {
LatchRunnable latchRunnable = new LatchRunnable();
- AppToolkitTaskExecutor.getInstance().executeOnMainThread(latchRunnable);
+ ArchTaskExecutor.getInstance().executeOnMainThread(latchRunnable);
return latchRunnable;
}
diff --git a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/JunitTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/JunitTaskExecutorRule.java
index cd4f8f5..c3366f3 100644
--- a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/JunitTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/JunitTaskExecutorRule.java
@@ -46,11 +46,11 @@
}
private void beforeStart() {
- AppToolkitTaskExecutor.getInstance().setDelegate(mTaskExecutor);
+ ArchTaskExecutor.getInstance().setDelegate(mTaskExecutor);
}
private void afterFinished() {
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
public TaskExecutor getTaskExecutor() {
diff --git a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/CountingTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/CountingTaskExecutorRule.java
index ad930aa..77133d5 100644
--- a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/CountingTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/CountingTaskExecutorRule.java
@@ -16,7 +16,7 @@
package android.arch.core.executor.testing;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.DefaultTaskExecutor;
import android.os.SystemClock;
@@ -39,7 +39,7 @@
@Override
protected void starting(Description description) {
super.starting(description);
- AppToolkitTaskExecutor.getInstance().setDelegate(new DefaultTaskExecutor() {
+ ArchTaskExecutor.getInstance().setDelegate(new DefaultTaskExecutor() {
@Override
public void executeOnDiskIO(Runnable runnable) {
super.executeOnDiskIO(new CountingRunnable(runnable));
@@ -55,7 +55,7 @@
@Override
protected void finished(Description description) {
super.finished(description);
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
private void increment() {
diff --git a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/InstantTaskExecutorRule.java b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/InstantTaskExecutorRule.java
index 07dcf1f..f88a3e3 100644
--- a/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/InstantTaskExecutorRule.java
+++ b/app-toolkit/core-testing/src/main/java/android/arch/core/executor/testing/InstantTaskExecutorRule.java
@@ -16,7 +16,7 @@
package android.arch.core.executor.testing;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.TaskExecutor;
import org.junit.rules.TestWatcher;
@@ -32,7 +32,7 @@
@Override
protected void starting(Description description) {
super.starting(description);
- AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+ ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
@Override
public void executeOnDiskIO(Runnable runnable) {
runnable.run();
@@ -53,6 +53,6 @@
@Override
protected void finished(Description description) {
super.finished(description);
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
}
diff --git a/app-toolkit/core-testing/src/test/java/android/arch/core/executor/testing/InstantTaskExecutorRuleTest.java b/app-toolkit/core-testing/src/test/java/android/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
index 4345fd1..0fdcbfb 100644
--- a/app-toolkit/core-testing/src/test/java/android/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
+++ b/app-toolkit/core-testing/src/test/java/android/arch/core/executor/testing/InstantTaskExecutorRuleTest.java
@@ -18,7 +18,7 @@
import static org.junit.Assert.assertTrue;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import org.junit.Rule;
import org.junit.Test;
@@ -46,7 +46,7 @@
return null;
}
});
- AppToolkitTaskExecutor.getInstance().executeOnMainThread(check);
+ ArchTaskExecutor.getInstance().executeOnMainThread(check);
check.get(1, TimeUnit.SECONDS);
}
@@ -60,7 +60,7 @@
return null;
}
});
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(check);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(check);
check.get(1, TimeUnit.SECONDS);
}
}
diff --git a/app-toolkit/runtime/src/main/java/android/arch/core/executor/AppToolkitTaskExecutor.java b/app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
similarity index 88%
rename from app-toolkit/runtime/src/main/java/android/arch/core/executor/AppToolkitTaskExecutor.java
rename to app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
index 7337f74..2401a73 100644
--- a/app-toolkit/runtime/src/main/java/android/arch/core/executor/AppToolkitTaskExecutor.java
+++ b/app-toolkit/runtime/src/main/java/android/arch/core/executor/ArchTaskExecutor.java
@@ -29,8 +29,8 @@
* @hide This API is not final.
*/
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-public class AppToolkitTaskExecutor extends TaskExecutor {
- private static volatile AppToolkitTaskExecutor sInstance;
+public class ArchTaskExecutor extends TaskExecutor {
+ private static volatile ArchTaskExecutor sInstance;
@NonNull
private TaskExecutor mDelegate;
@@ -54,7 +54,7 @@
}
};
- private AppToolkitTaskExecutor() {
+ private ArchTaskExecutor() {
mDefaultTaskExecutor = new DefaultTaskExecutor();
mDelegate = mDefaultTaskExecutor;
}
@@ -62,15 +62,15 @@
/**
* Returns an instance of the task executor.
*
- * @return The singleton AppToolkitTaskExecutor.
+ * @return The singleton ArchTaskExecutor.
*/
- public static AppToolkitTaskExecutor getInstance() {
+ public static ArchTaskExecutor getInstance() {
if (sInstance != null) {
return sInstance;
}
- synchronized (AppToolkitTaskExecutor.class) {
+ synchronized (ArchTaskExecutor.class) {
if (sInstance == null) {
- sInstance = new AppToolkitTaskExecutor();
+ sInstance = new ArchTaskExecutor();
}
}
return sInstance;
diff --git a/buildSrc/init.gradle b/buildSrc/init.gradle
index ec8685d..f09c777 100644
--- a/buildSrc/init.gradle
+++ b/buildSrc/init.gradle
@@ -64,7 +64,7 @@
}
def setSdkInLocalPropertiesFile() {
- ext.buildToolsVersion = '26.0.0'
+ ext.buildToolsVersion = '27.0.0'
final String fullSdkPath = getFullSdkPath();
if (file(fullSdkPath).exists()) {
gradle.ext.currentSdk = 26
diff --git a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
index 3905ca5..0dcd902 100644
--- a/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
+++ b/compat/java/android/support/v4/accessibilityservice/AccessibilityServiceInfoCompat.java
@@ -20,6 +20,8 @@
import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.pm.PackageManager;
import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.view.View;
/**
@@ -188,8 +190,9 @@
* @param packageManager The current package manager
* @return The localized description.
*/
+ @Nullable
public static String loadDescription(
- AccessibilityServiceInfo info, PackageManager packageManager) {
+ @NonNull AccessibilityServiceInfo info, @NonNull PackageManager packageManager) {
if (Build.VERSION.SDK_INT >= 16) {
return info.loadDescription(packageManager);
} else {
@@ -206,6 +209,7 @@
* @param feedbackType The feedback type.
* @return The string representation.
*/
+ @NonNull
public static String feedbackTypeToString(int feedbackType) {
StringBuilder builder = new StringBuilder();
builder.append("[");
@@ -245,6 +249,7 @@
* @param flag The flag.
* @return The string representation.
*/
+ @Nullable
public static String flagToString(int flag) {
switch (flag) {
case AccessibilityServiceInfo.DEFAULT:
@@ -276,7 +281,7 @@
* @see #CAPABILITY_CAN_REQUEST_ENHANCED_WEB_ACCESSIBILITY
* @see #CAPABILITY_CAN_FILTER_KEY_EVENTS
*/
- public static int getCapabilities(AccessibilityServiceInfo info) {
+ public static int getCapabilities(@NonNull AccessibilityServiceInfo info) {
if (Build.VERSION.SDK_INT >= 18) {
return info.getCapabilities();
} else {
@@ -296,6 +301,7 @@
* @param capability The capability.
* @return The string representation.
*/
+ @NonNull
public static String capabilityToString(int capability) {
switch (capability) {
case CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT:
diff --git a/compat/java/android/support/v4/app/ActivityCompat.java b/compat/java/android/support/v4/app/ActivityCompat.java
index a26b64c..2ce5a30 100644
--- a/compat/java/android/support/v4/app/ActivityCompat.java
+++ b/compat/java/android/support/v4/app/ActivityCompat.java
@@ -148,8 +148,8 @@
* supplied here; there are no supported definitions for
* building it manually.
*/
- public static void startActivityForResult(Activity activity, Intent intent, int requestCode,
- @Nullable Bundle options) {
+ public static void startActivityForResult(@NonNull Activity activity, @NonNull Intent intent,
+ int requestCode, @Nullable Bundle options) {
if (Build.VERSION.SDK_INT >= 16) {
activity.startActivityForResult(intent, requestCode, options);
} else {
@@ -183,9 +183,10 @@
* supplied here; there are no supported definitions for
* building it manually.
*/
- public static void startIntentSenderForResult(Activity activity, IntentSender intent,
- int requestCode, Intent fillInIntent, int flagsMask, int flagsValues,
- int extraFlags, @Nullable Bundle options) throws IntentSender.SendIntentException {
+ public static void startIntentSenderForResult(@NonNull Activity activity,
+ @NonNull IntentSender intent, int requestCode, @Nullable Intent fillInIntent,
+ int flagsMask, int flagsValues, int extraFlags, @Nullable Bundle options)
+ throws IntentSender.SendIntentException {
if (Build.VERSION.SDK_INT >= 16) {
activity.startIntentSenderForResult(intent, requestCode, fillInIntent, flagsMask,
flagsValues, extraFlags, options);
@@ -202,7 +203,7 @@
* <p>On Android 4.1+ calling this method will call through to the native version of this
* method. For other platforms {@link Activity#finish()} will be called instead.</p>
*/
- public static void finishAffinity(Activity activity) {
+ public static void finishAffinity(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT >= 16) {
activity.finishAffinity();
} else {
@@ -219,7 +220,7 @@
* <p>On Android 4.4 or lower, this method only finishes the Activity with no
* special exit transition.</p>
*/
- public static void finishAfterTransition(Activity activity) {
+ public static void finishAfterTransition(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT >= 21) {
activity.finishAfterTransition();
} else {
@@ -244,7 +245,7 @@
* referrer information, applications can spoof it.</p>
*/
@Nullable
- public static Uri getReferrer(Activity activity) {
+ public static Uri getReferrer(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT >= 22) {
return activity.getReferrer();
}
@@ -268,8 +269,8 @@
*
* @param callback Used to manipulate shared element transitions on the launched Activity.
*/
- public static void setEnterSharedElementCallback(Activity activity,
- SharedElementCallback callback) {
+ public static void setEnterSharedElementCallback(@NonNull Activity activity,
+ @Nullable SharedElementCallback callback) {
if (Build.VERSION.SDK_INT >= 23) {
android.app.SharedElementCallback frameworkCallback = callback != null
? new SharedElementCallback23Impl(callback)
@@ -292,8 +293,8 @@
*
* @param callback Used to manipulate shared element transitions on the launching Activity.
*/
- public static void setExitSharedElementCallback(Activity activity,
- SharedElementCallback callback) {
+ public static void setExitSharedElementCallback(@NonNull Activity activity,
+ @Nullable SharedElementCallback callback) {
if (Build.VERSION.SDK_INT >= 23) {
android.app.SharedElementCallback frameworkCallback = callback != null
? new SharedElementCallback23Impl(callback)
@@ -307,13 +308,13 @@
}
}
- public static void postponeEnterTransition(Activity activity) {
+ public static void postponeEnterTransition(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT >= 21) {
activity.postponeEnterTransition();
}
}
- public static void startPostponedEnterTransition(Activity activity) {
+ public static void startPostponedEnterTransition(@NonNull Activity activity) {
if (Build.VERSION.SDK_INT >= 21) {
activity.startPostponedEnterTransition();
}
diff --git a/compat/java/android/support/v4/app/ActivityOptionsCompat.java b/compat/java/android/support/v4/app/ActivityOptionsCompat.java
index 2957c50..6676805 100644
--- a/compat/java/android/support/v4/app/ActivityOptionsCompat.java
+++ b/compat/java/android/support/v4/app/ActivityOptionsCompat.java
@@ -24,6 +24,7 @@
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v4.util.Pair;
@@ -60,7 +61,8 @@
* @return Returns a new ActivityOptions object that you can use to supply
* these options as the options Bundle when starting an activity.
*/
- public static ActivityOptionsCompat makeCustomAnimation(Context context,
+ @NonNull
+ public static ActivityOptionsCompat makeCustomAnimation(@NonNull Context context,
int enterResId, int exitResId) {
if (Build.VERSION.SDK_INT >= 16) {
return createImpl(ActivityOptions.makeCustomAnimation(context, enterResId, exitResId));
@@ -88,7 +90,8 @@
* @return Returns a new ActivityOptions object that you can use to supply
* these options as the options Bundle when starting an activity.
*/
- public static ActivityOptionsCompat makeScaleUpAnimation(View source,
+ @NonNull
+ public static ActivityOptionsCompat makeScaleUpAnimation(@NonNull View source,
int startX, int startY, int startWidth, int startHeight) {
if (Build.VERSION.SDK_INT >= 16) {
return createImpl(ActivityOptions.makeScaleUpAnimation(
@@ -111,7 +114,8 @@
* @return Returns a new ActivityOptions object that you can use to
* supply these options as the options Bundle when starting an activity.
*/
- public static ActivityOptionsCompat makeClipRevealAnimation(View source,
+ @NonNull
+ public static ActivityOptionsCompat makeClipRevealAnimation(@NonNull View source,
int startX, int startY, int width, int height) {
if (Build.VERSION.SDK_INT >= 23) {
return createImpl(ActivityOptions.makeClipRevealAnimation(
@@ -139,8 +143,9 @@
* @return Returns a new ActivityOptions object that you can use to supply
* these options as the options Bundle when starting an activity.
*/
- public static ActivityOptionsCompat makeThumbnailScaleUpAnimation(View source,
- Bitmap thumbnail, int startX, int startY) {
+ @NonNull
+ public static ActivityOptionsCompat makeThumbnailScaleUpAnimation(@NonNull View source,
+ @NonNull Bitmap thumbnail, int startX, int startY) {
if (Build.VERSION.SDK_INT >= 16) {
return createImpl(ActivityOptions.makeThumbnailScaleUpAnimation(
source, thumbnail, startX, startY));
@@ -166,8 +171,9 @@
* @return Returns a new ActivityOptions object that you can use to
* supply these options as the options Bundle when starting an activity.
*/
- public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity,
- View sharedElement, String sharedElementName) {
+ @NonNull
+ public static ActivityOptionsCompat makeSceneTransitionAnimation(@NonNull Activity activity,
+ @NonNull View sharedElement, @NonNull String sharedElementName) {
if (Build.VERSION.SDK_INT >= 21) {
return createImpl(ActivityOptions.makeSceneTransitionAnimation(
activity, sharedElement, sharedElementName));
@@ -192,8 +198,9 @@
* @return Returns a new ActivityOptions object that you can use to
* supply these options as the options Bundle when starting an activity.
*/
+ @NonNull
@SuppressWarnings("unchecked")
- public static ActivityOptionsCompat makeSceneTransitionAnimation(Activity activity,
+ public static ActivityOptionsCompat makeSceneTransitionAnimation(@NonNull Activity activity,
Pair<View, String>... sharedElements) {
if (Build.VERSION.SDK_INT >= 21) {
android.util.Pair<View, String>[] pairs = null;
@@ -219,6 +226,7 @@
* {@link android.R.attr#launchMode launchMode} values of
* <code>singleInstance</code> or <code>singleTask</code>.
*/
+ @NonNull
public static ActivityOptionsCompat makeTaskLaunchBehind() {
if (Build.VERSION.SDK_INT >= 21) {
return createImpl(ActivityOptions.makeTaskLaunchBehind());
@@ -230,6 +238,7 @@
* Create a basic ActivityOptions that has no special animation associated with it.
* Other options can still be set.
*/
+ @NonNull
public static ActivityOptionsCompat makeBasic() {
if (Build.VERSION.SDK_INT >= 23) {
return createImpl(ActivityOptions.makeBasic());
@@ -314,6 +323,7 @@
* {@link android.content.pm.PackageManager#FEATURE_PICTURE_IN_PICTURE} enabled.
* @param screenSpacePixelRect Launch bounds to use for the activity or null for fullscreen.
*/
+ @NonNull
public ActivityOptionsCompat setLaunchBounds(@Nullable Rect screenSpacePixelRect) {
return this;
}
@@ -335,6 +345,7 @@
* object; you must not modify it, but can supply it to the startActivity
* methods that take an options Bundle.
*/
+ @Nullable
public Bundle toBundle() {
return null;
}
@@ -344,7 +355,7 @@
* otherOptions. Any values defined in otherOptions replace those in the
* base options.
*/
- public void update(ActivityOptionsCompat otherOptions) {
+ public void update(@NonNull ActivityOptionsCompat otherOptions) {
// Do nothing.
}
@@ -372,7 +383,7 @@
*
* @param receiver A broadcast receiver that will receive the report.
*/
- public void requestUsageTimeReport(PendingIntent receiver) {
+ public void requestUsageTimeReport(@NonNull PendingIntent receiver) {
// Do nothing.
}
}
diff --git a/compat/java/android/support/v4/app/AlarmManagerCompat.java b/compat/java/android/support/v4/app/AlarmManagerCompat.java
index 5a4582b..a297cb5 100644
--- a/compat/java/android/support/v4/app/AlarmManagerCompat.java
+++ b/compat/java/android/support/v4/app/AlarmManagerCompat.java
@@ -19,6 +19,7 @@
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.os.Build;
+import android.support.annotation.NonNull;
/**
* Compatibility library for {@link AlarmManager} with fallbacks for older platforms.
@@ -52,8 +53,8 @@
* @see android.content.Context#registerReceiver
* @see android.content.Intent#filterEquals
*/
- public static void setAlarmClock(AlarmManager alarmManager, long triggerTime,
- PendingIntent showIntent, PendingIntent operation) {
+ public static void setAlarmClock(@NonNull AlarmManager alarmManager, long triggerTime,
+ @NonNull PendingIntent showIntent, @NonNull PendingIntent operation) {
if (Build.VERSION.SDK_INT >= 21) {
alarmManager.setAlarmClock(new AlarmManager.AlarmClockInfo(triggerTime, showIntent),
operation);
@@ -110,8 +111,8 @@
* @see AlarmManager#RTC
* @see AlarmManager#RTC_WAKEUP
*/
- public static void setAndAllowWhileIdle(AlarmManager alarmManager, int type,
- long triggerAtMillis, PendingIntent operation) {
+ public static void setAndAllowWhileIdle(@NonNull AlarmManager alarmManager, int type,
+ long triggerAtMillis, @NonNull PendingIntent operation) {
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setAndAllowWhileIdle(type, triggerAtMillis, operation);
} else {
@@ -155,8 +156,8 @@
* @see AlarmManager#RTC
* @see AlarmManager#RTC_WAKEUP
*/
- public static void setExact(AlarmManager alarmManager, int type, long triggerAtMillis,
- PendingIntent operation) {
+ public static void setExact(@NonNull AlarmManager alarmManager, int type, long triggerAtMillis,
+ @NonNull PendingIntent operation) {
if (Build.VERSION.SDK_INT >= 19) {
alarmManager.setExact(type, triggerAtMillis, operation);
} else {
@@ -215,8 +216,8 @@
* @see AlarmManager#RTC
* @see AlarmManager#RTC_WAKEUP
*/
- public static void setExactAndAllowWhileIdle(AlarmManager alarmManager, int type,
- long triggerAtMillis, PendingIntent operation) {
+ public static void setExactAndAllowWhileIdle(@NonNull AlarmManager alarmManager, int type,
+ long triggerAtMillis, @NonNull PendingIntent operation) {
if (Build.VERSION.SDK_INT >= 23) {
alarmManager.setExactAndAllowWhileIdle(type, triggerAtMillis, operation);
} else {
diff --git a/compat/java/android/support/v4/app/AppOpsManagerCompat.java b/compat/java/android/support/v4/app/AppOpsManagerCompat.java
index ce2d2c6..7e97199 100644
--- a/compat/java/android/support/v4/app/AppOpsManagerCompat.java
+++ b/compat/java/android/support/v4/app/AppOpsManagerCompat.java
@@ -21,6 +21,7 @@
import android.app.AppOpsManager;
import android.content.Context;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
/**
* Helper for accessing features in {@link android.app.AppOpsManager}.
@@ -56,6 +57,7 @@
* @param permission The permission.
* @return The app op associated with the permission or null.
*/
+ @Nullable
public static String permissionToOp(@NonNull String permission) {
if (SDK_INT >= 23) {
return AppOpsManager.permissionToOp(permission);
diff --git a/compat/java/android/support/v4/app/BundleCompat.java b/compat/java/android/support/v4/app/BundleCompat.java
index e5fc302..21d730d 100644
--- a/compat/java/android/support/v4/app/BundleCompat.java
+++ b/compat/java/android/support/v4/app/BundleCompat.java
@@ -19,6 +19,8 @@
import android.os.Build;
import android.os.Bundle;
import android.os.IBinder;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
@@ -94,7 +96,8 @@
* @param key The key to use while getting the {@link IBinder}.
* @return The {@link IBinder} that was obtained.
*/
- public static IBinder getBinder(Bundle bundle, String key) {
+ @Nullable
+ public static IBinder getBinder(@NonNull Bundle bundle, @Nullable String key) {
if (Build.VERSION.SDK_INT >= 18) {
return bundle.getBinder(key);
} else {
@@ -109,7 +112,8 @@
* @param key The key to use while putting the {@link IBinder}.
* @param binder The {@link IBinder} to put.
*/
- public static void putBinder(Bundle bundle, String key, IBinder binder) {
+ public static void putBinder(@NonNull Bundle bundle, @Nullable String key,
+ @Nullable IBinder binder) {
if (Build.VERSION.SDK_INT >= 18) {
bundle.putBinder(key, binder);
} else {
diff --git a/compat/java/android/support/v4/app/NotificationManagerCompat.java b/compat/java/android/support/v4/app/NotificationManagerCompat.java
index 93775ec..1a0f1bc 100644
--- a/compat/java/android/support/v4/app/NotificationManagerCompat.java
+++ b/compat/java/android/support/v4/app/NotificationManagerCompat.java
@@ -36,6 +36,8 @@
import android.os.RemoteException;
import android.provider.Settings;
import android.support.annotation.GuardedBy;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.util.Log;
import java.lang.reflect.Field;
@@ -144,7 +146,8 @@
public static final int IMPORTANCE_MAX = 5;
/** Get a {@link NotificationManagerCompat} instance for a provided context. */
- public static NotificationManagerCompat from(Context context) {
+ @NonNull
+ public static NotificationManagerCompat from(@NonNull Context context) {
return new NotificationManagerCompat(context);
}
@@ -167,7 +170,7 @@
* @param tag the string identifier of the notification.
* @param id the ID of the notification
*/
- public void cancel(String tag, int id) {
+ public void cancel(@Nullable String tag, int id) {
mNotificationManager.cancel(tag, id);
if (Build.VERSION.SDK_INT <= MAX_SIDE_CHANNEL_SDK_VERSION) {
pushSideChannelQueue(new CancelTask(mContext.getPackageName(), id, tag));
@@ -197,7 +200,7 @@
* @param id the ID of the notification. The pair (tag, id) must be unique within your app.
* @param notification the notification to post to the system
*/
- public void notify(String tag, int id, Notification notification) {
+ public void notify(@Nullable String tag, int id, @NonNull Notification notification) {
if (useSideChannelForNotification(notification)) {
pushSideChannelQueue(new NotifyTask(mContext.getPackageName(), id, tag, notification));
// Cancel this notification in notification manager if it just transitioned to being
@@ -253,7 +256,8 @@
/**
* Get the set of packages that have an enabled notification listener component within them.
*/
- public static Set<String> getEnabledListenerPackages(Context context) {
+ @NonNull
+ public static Set<String> getEnabledListenerPackages(@NonNull Context context) {
final String enabledNotificationListeners = Settings.Secure.getString(
context.getContentResolver(),
SETTING_ENABLED_NOTIFICATION_LISTENERS);
diff --git a/compat/java/android/support/v4/app/ServiceCompat.java b/compat/java/android/support/v4/app/ServiceCompat.java
index 1676ee8..2e63b23 100644
--- a/compat/java/android/support/v4/app/ServiceCompat.java
+++ b/compat/java/android/support/v4/app/ServiceCompat.java
@@ -22,6 +22,7 @@
import android.app.Service;
import android.os.Build;
import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
import android.support.annotation.RestrictTo;
import java.lang.annotation.Retention;
@@ -92,7 +93,7 @@
* {@link #STOP_FOREGROUND_DETACH}.
* @see Service#startForeground(int, Notification)
*/
- public static void stopForeground(Service service, @StopForegroundFlags int flags) {
+ public static void stopForeground(@NonNull Service service, @StopForegroundFlags int flags) {
if (Build.VERSION.SDK_INT >= 24) {
service.stopForeground(flags);
} else {
diff --git a/compat/java/android/support/v4/content/ContextCompat.java b/compat/java/android/support/v4/content/ContextCompat.java
index fdbe32f..8a4fd7a 100644
--- a/compat/java/android/support/v4/content/ContextCompat.java
+++ b/compat/java/android/support/v4/content/ContextCompat.java
@@ -79,7 +79,7 @@
* length-1 will correspond to the top activity on the resulting task stack.
* @return true if the underlying API was available and the call was successful, false otherwise
*/
- public static boolean startActivities(Context context, Intent[] intents) {
+ public static boolean startActivities(@NonNull Context context, @NonNull Intent[] intents) {
return startActivities(context, intents, null);
}
@@ -110,7 +110,8 @@
* See {@link android.content.Context#startActivity(Intent, android.os.Bundle)}
* @return true if the underlying API was available and the call was successful, false otherwise
*/
- public static boolean startActivities(Context context, Intent[] intents, Bundle options) {
+ public static boolean startActivities(@NonNull Context context, @NonNull Intent[] intents,
+ @Nullable Bundle options) {
if (Build.VERSION.SDK_INT >= 16) {
context.startActivities(intents, options);
} else {
@@ -136,7 +137,8 @@
* supplied here; there are no supported definitions for
* building it manually.
*/
- public static void startActivity(Context context, Intent intent, @Nullable Bundle options) {
+ public static void startActivity(@NonNull Context context, @NonNull Intent intent,
+ @Nullable Bundle options) {
if (Build.VERSION.SDK_INT >= 16) {
context.startActivity(intent, options);
} else {
@@ -159,7 +161,8 @@
*
* @see ApplicationInfo#dataDir
*/
- public static File getDataDir(Context context) {
+ @Nullable
+ public static File getDataDir(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 24) {
return context.getDataDir();
} else {
@@ -211,7 +214,8 @@
* @see Context#getObbDir()
* @see EnvironmentCompat#getStorageState(File)
*/
- public static File[] getObbDirs(Context context) {
+ @NonNull
+ public static File[] getObbDirs(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 19) {
return context.getObbDirs();
} else {
@@ -263,7 +267,8 @@
* @see Context#getExternalFilesDir(String)
* @see EnvironmentCompat#getStorageState(File)
*/
- public static File[] getExternalFilesDirs(Context context, String type) {
+ @NonNull
+ public static File[] getExternalFilesDirs(@NonNull Context context, @Nullable String type) {
if (Build.VERSION.SDK_INT >= 19) {
return context.getExternalFilesDirs(type);
} else {
@@ -315,7 +320,8 @@
* @see Context#getExternalCacheDir()
* @see EnvironmentCompat#getStorageState(File)
*/
- public static File[] getExternalCacheDirs(Context context) {
+ @NonNull
+ public static File[] getExternalCacheDirs(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 19) {
return context.getExternalCacheDirs();
} else {
@@ -346,7 +352,8 @@
* The value 0 is an invalid identifier.
* @return Drawable An object that can be used to draw this resource.
*/
- public static final Drawable getDrawable(Context context, @DrawableRes int id) {
+ @Nullable
+ public static final Drawable getDrawable(@NonNull Context context, @DrawableRes int id) {
if (Build.VERSION.SDK_INT >= 21) {
return context.getDrawable(id);
} else if (Build.VERSION.SDK_INT >= 16) {
@@ -382,7 +389,9 @@
* @throws android.content.res.Resources.NotFoundException if the given ID
* does not exist.
*/
- public static final ColorStateList getColorStateList(Context context, @ColorRes int id) {
+ @Nullable
+ public static final ColorStateList getColorStateList(@NonNull Context context,
+ @ColorRes int id) {
if (Build.VERSION.SDK_INT >= 23) {
return context.getColorStateList(id);
} else {
@@ -404,7 +413,7 @@
* does not exist.
*/
@ColorInt
- public static final int getColor(Context context, @ColorRes int id) {
+ public static final int getColor(@NonNull Context context, @ColorRes int id) {
if (Build.VERSION.SDK_INT >= 23) {
return context.getColor(id);
} else {
@@ -444,7 +453,8 @@
*
* @see android.content.Context#getFilesDir()
*/
- public static final File getNoBackupFilesDir(Context context) {
+ @Nullable
+ public static final File getNoBackupFilesDir(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 21) {
return context.getNoBackupFilesDir();
} else {
@@ -468,7 +478,7 @@
*
* @return The path of the directory holding application code cache files.
*/
- public static File getCodeCacheDir(Context context) {
+ public static File getCodeCacheDir(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 21) {
return context.getCodeCacheDir();
} else {
@@ -522,7 +532,8 @@
*
* @see ContextCompat#isDeviceProtectedStorage(Context)
*/
- public static Context createDeviceProtectedStorageContext(Context context) {
+ @Nullable
+ public static Context createDeviceProtectedStorageContext(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 24) {
return context.createDeviceProtectedStorageContext();
} else {
@@ -536,7 +547,7 @@
*
* @see ContextCompat#createDeviceProtectedStorageContext(Context)
*/
- public static boolean isDeviceProtectedStorage(Context context) {
+ public static boolean isDeviceProtectedStorage(@NonNull Context context) {
if (Build.VERSION.SDK_INT >= 24) {
return context.isDeviceProtectedStorage();
} else {
@@ -554,7 +565,7 @@
* @see Context#startForegeroundService()
* @see Context#startService()
*/
- public static void startForegroundService(Context context, Intent intent) {
+ public static void startForegroundService(@NonNull Context context, @NonNull Intent intent) {
if (Build.VERSION.SDK_INT >= 26) {
context.startForegroundService(intent);
} else {
diff --git a/compat/java/android/support/v4/content/IntentCompat.java b/compat/java/android/support/v4/content/IntentCompat.java
index 1a7295b..f5b3a0b 100644
--- a/compat/java/android/support/v4/content/IntentCompat.java
+++ b/compat/java/android/support/v4/content/IntentCompat.java
@@ -18,6 +18,7 @@
import android.content.Intent;
import android.os.Build;
+import android.support.annotation.NonNull;
/**
* Helper for accessing features in {@link android.content.Intent}.
@@ -69,8 +70,9 @@
* @return Returns a newly created Intent that can be used to launch the
* activity as a main application entry.
*/
- public static Intent makeMainSelectorActivity(String selectorAction,
- String selectorCategory) {
+ @NonNull
+ public static Intent makeMainSelectorActivity(@NonNull String selectorAction,
+ @NonNull String selectorCategory) {
if (Build.VERSION.SDK_INT >= 15) {
return Intent.makeMainSelectorActivity(selectorAction, selectorCategory);
} else {
diff --git a/compat/java/android/support/v4/content/res/TypedArrayUtils.java b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
index e4d6b29..64cb981 100644
--- a/compat/java/android/support/v4/content/res/TypedArrayUtils.java
+++ b/compat/java/android/support/v4/content/res/TypedArrayUtils.java
@@ -24,6 +24,7 @@
import android.support.annotation.AnyRes;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
import android.support.annotation.StyleableRes;
import android.util.AttributeSet;
@@ -80,7 +81,7 @@
* {@code defaultValue} if it does not exist.
*/
public static boolean getNamedBoolean(@NonNull TypedArray a, @NonNull XmlPullParser parser,
- String attrName, @StyleableRes int resId, boolean defaultValue) {
+ @NonNull String attrName, @StyleableRes int resId, boolean defaultValue) {
final boolean hasAttr = hasAttribute(parser, attrName);
if (!hasAttr) {
return defaultValue;
@@ -97,7 +98,7 @@
* {@code defaultValue} if it does not exist.
*/
public static int getNamedInt(@NonNull TypedArray a, @NonNull XmlPullParser parser,
- String attrName, @StyleableRes int resId, int defaultValue) {
+ @NonNull String attrName, @StyleableRes int resId, int defaultValue) {
final boolean hasAttr = hasAttribute(parser, attrName);
if (!hasAttr) {
return defaultValue;
@@ -115,7 +116,7 @@
*/
@ColorInt
public static int getNamedColor(@NonNull TypedArray a, @NonNull XmlPullParser parser,
- String attrName, @StyleableRes int resId, @ColorInt int defaultValue) {
+ @NonNull String attrName, @StyleableRes int resId, @ColorInt int defaultValue) {
final boolean hasAttr = hasAttribute(parser, attrName);
if (!hasAttr) {
return defaultValue;
@@ -133,7 +134,7 @@
*/
@AnyRes
public static int getNamedResourceId(@NonNull TypedArray a, @NonNull XmlPullParser parser,
- String attrName, @StyleableRes int resId, @AnyRes int defaultValue) {
+ @NonNull String attrName, @StyleableRes int resId, @AnyRes int defaultValue) {
final boolean hasAttr = hasAttribute(parser, attrName);
if (!hasAttr) {
return defaultValue;
@@ -149,8 +150,9 @@
* @return a string value in the {@link TypedArray} with the specified {@code resId}, or
* null if it does not exist.
*/
+ @Nullable
public static String getNamedString(@NonNull TypedArray a, @NonNull XmlPullParser parser,
- String attrName, @StyleableRes int resId) {
+ @NonNull String attrName, @StyleableRes int resId) {
final boolean hasAttr = hasAttribute(parser, attrName);
if (!hasAttr) {
return null;
@@ -164,8 +166,9 @@
* and return a temporary object holding its data. This object is only
* valid until the next call on to {@link TypedArray}.
*/
- public static TypedValue peekNamedValue(TypedArray a, XmlPullParser parser, String attrName,
- int resId) {
+ @Nullable
+ public static TypedValue peekNamedValue(@NonNull TypedArray a, @NonNull XmlPullParser parser,
+ @NonNull String attrName, int resId) {
final boolean hasAttr = hasAttribute(parser, attrName);
if (!hasAttr) {
return null;
@@ -178,8 +181,9 @@
* Obtains styled attributes from the theme, if available, or unstyled
* resources if the theme is null.
*/
- public static TypedArray obtainAttributes(
- Resources res, Resources.Theme theme, AttributeSet set, int[] attrs) {
+ @NonNull
+ public static TypedArray obtainAttributes(@NonNull Resources res,
+ @Nullable Resources.Theme theme, @NonNull AttributeSet set, @NonNull int[] attrs) {
if (theme == null) {
return res.obtainAttributes(set, attrs);
}
@@ -190,7 +194,7 @@
* @return a boolean value of {@code index}. If it does not exist, a boolean value of
* {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
*/
- public static boolean getBoolean(TypedArray a, @StyleableRes int index,
+ public static boolean getBoolean(@NonNull TypedArray a, @StyleableRes int index,
@StyleableRes int fallbackIndex, boolean defaultValue) {
boolean val = a.getBoolean(fallbackIndex, defaultValue);
return a.getBoolean(index, val);
@@ -200,7 +204,8 @@
* @return a drawable value of {@code index}. If it does not exist, a drawable value of
* {@code fallbackIndex}. If it still does not exist, {@code null}.
*/
- public static Drawable getDrawable(TypedArray a, @StyleableRes int index,
+ @Nullable
+ public static Drawable getDrawable(@NonNull TypedArray a, @StyleableRes int index,
@StyleableRes int fallbackIndex) {
Drawable val = a.getDrawable(index);
if (val == null) {
@@ -213,7 +218,7 @@
* @return an int value of {@code index}. If it does not exist, an int value of
* {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
*/
- public static int getInt(TypedArray a, @StyleableRes int index,
+ public static int getInt(@NonNull TypedArray a, @StyleableRes int index,
@StyleableRes int fallbackIndex, int defaultValue) {
int val = a.getInt(fallbackIndex, defaultValue);
return a.getInt(index, val);
@@ -224,7 +229,7 @@
* {@code fallbackIndex}. If it still does not exist, {@code defaultValue}.
*/
@AnyRes
- public static int getResourceId(TypedArray a, @StyleableRes int index,
+ public static int getResourceId(@NonNull TypedArray a, @StyleableRes int index,
@StyleableRes int fallbackIndex, @AnyRes int defaultValue) {
int val = a.getResourceId(fallbackIndex, defaultValue);
return a.getResourceId(index, val);
@@ -234,7 +239,8 @@
* @return a string value of {@code index}. If it does not exist, a string value of
* {@code fallbackIndex}. If it still does not exist, {@code null}.
*/
- public static String getString(TypedArray a, @StyleableRes int index,
+ @Nullable
+ public static String getString(@NonNull TypedArray a, @StyleableRes int index,
@StyleableRes int fallbackIndex) {
String val = a.getString(index);
if (val == null) {
@@ -249,7 +255,8 @@
* @return a text value of {@code index}. If it does not exist, a text value of
* {@code fallbackIndex}. If it still does not exist, {@code null}.
*/
- public static CharSequence getText(TypedArray a, @StyleableRes int index,
+ @Nullable
+ public static CharSequence getText(@NonNull TypedArray a, @StyleableRes int index,
@StyleableRes int fallbackIndex) {
CharSequence val = a.getText(index);
if (val == null) {
@@ -264,7 +271,8 @@
* @return a string array value of {@code index}. If it does not exist, a string array value
* of {@code fallbackIndex}. If it still does not exist, {@code null}.
*/
- public static CharSequence[] getTextArray(TypedArray a, @StyleableRes int index,
+ @Nullable
+ public static CharSequence[] getTextArray(@NonNull TypedArray a, @StyleableRes int index,
@StyleableRes int fallbackIndex) {
CharSequence[] val = a.getTextArray(index);
if (val == null) {
@@ -277,7 +285,7 @@
* @return The resource ID value in the {@code context} specified by {@code attr}. If it does
* not exist, {@code fallbackAttr}.
*/
- public static int getAttr(Context context, int attr, int fallbackAttr) {
+ public static int getAttr(@NonNull Context context, int attr, int fallbackAttr) {
TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(attr, value, true);
if (value.resourceId != 0) {
diff --git a/compat/java/android/support/v4/graphics/BitmapCompat.java b/compat/java/android/support/v4/graphics/BitmapCompat.java
index 20caf80..acc37b1 100644
--- a/compat/java/android/support/v4/graphics/BitmapCompat.java
+++ b/compat/java/android/support/v4/graphics/BitmapCompat.java
@@ -17,6 +17,7 @@
import android.graphics.Bitmap;
import android.os.Build;
+import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
/**
@@ -71,11 +72,11 @@
}
}
- public static boolean hasMipMap(Bitmap bitmap) {
+ public static boolean hasMipMap(@NonNull Bitmap bitmap) {
return IMPL.hasMipMap(bitmap);
}
- public static void setHasMipMap(Bitmap bitmap, boolean hasMipMap) {
+ public static void setHasMipMap(@NonNull Bitmap bitmap, boolean hasMipMap) {
IMPL.setHasMipMap(bitmap, hasMipMap);
}
@@ -86,7 +87,7 @@
* @param bitmap the bitmap in which to return its allocation size
* @return the allocation size in bytes
*/
- public static int getAllocationByteCount(Bitmap bitmap) {
+ public static int getAllocationByteCount(@NonNull Bitmap bitmap) {
return IMPL.getAllocationByteCount(bitmap);
}
diff --git a/compat/java/android/support/v4/graphics/TypefaceCompat.java b/compat/java/android/support/v4/graphics/TypefaceCompat.java
index 6d114b6..b142a5f 100644
--- a/compat/java/android/support/v4/graphics/TypefaceCompat.java
+++ b/compat/java/android/support/v4/graphics/TypefaceCompat.java
@@ -82,7 +82,8 @@
*
* @return null if not found.
*/
- public static Typeface findFromCache(Resources resources, int id, int style) {
+ @Nullable
+ public static Typeface findFromCache(@NonNull Resources resources, int id, int style) {
return sTypefaceCache.get(createResourceUid(resources, id, style));
}
@@ -103,8 +104,10 @@
*
* @return null if failed to create.
*/
+ @Nullable
public static Typeface createFromResourcesFamilyXml(
- Context context, FamilyResourceEntry entry, Resources resources, int id, int style,
+ @NonNull Context context, @NonNull FamilyResourceEntry entry,
+ @NonNull Resources resources, int id, int style,
@Nullable TextView targetView) {
Typeface typeface;
if (entry instanceof ProviderResourceEntry) {
@@ -127,7 +130,8 @@
*/
@Nullable
public static Typeface createFromResourcesFontFile(
- Context context, Resources resources, int id, String path, int style) {
+ @NonNull Context context, @NonNull Resources resources, int id, String path,
+ int style) {
Typeface typeface = sTypefaceCompatImpl.createFromResourcesFontFile(
context, resources, id, path, style);
if (typeface != null) {
@@ -139,7 +143,8 @@
/**
* Create a Typeface from a given FontInfo list and a map that matches them to ByteBuffers.
*/
- public static Typeface createFromFontInfo(Context context,
+ @Nullable
+ public static Typeface createFromFontInfo(@NonNull Context context,
@Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts, int style) {
return sTypefaceCompatImpl.createFromFontInfo(context, cancellationSignal, fonts, style);
}
diff --git a/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java b/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
index 50d246b..22d39ac 100644
--- a/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
+++ b/compat/java/android/support/v4/hardware/display/DisplayManagerCompat.java
@@ -19,6 +19,8 @@
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.view.Display;
import android.view.WindowManager;
@@ -52,7 +54,8 @@
/**
* Gets an instance of the display manager given the context.
*/
- public static DisplayManagerCompat getInstance(Context context) {
+ @NonNull
+ public static DisplayManagerCompat getInstance(@NonNull Context context) {
synchronized (sInstances) {
DisplayManagerCompat instance = sInstances.get(context);
if (instance == null) {
@@ -76,6 +79,7 @@
* @param displayId The logical display id.
* @return The display object, or null if there is no valid display with the given id.
*/
+ @Nullable
public abstract Display getDisplay(int displayId);
/**
@@ -83,6 +87,7 @@
*
* @return An array containing all displays.
*/
+ @NonNull
public abstract Display[] getDisplays();
/**
@@ -101,6 +106,7 @@
*
* @see #DISPLAY_CATEGORY_PRESENTATION
*/
+ @NonNull
public abstract Display[] getDisplays(String category);
private static class DisplayManagerCompatApi14Impl extends DisplayManagerCompat {
diff --git a/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java b/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
index 5e23c68..68f9476 100644
--- a/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
+++ b/compat/java/android/support/v4/hardware/fingerprint/FingerprintManagerCompat.java
@@ -44,7 +44,8 @@
private final Context mContext;
/** Get a {@link FingerprintManagerCompat} instance for a provided context. */
- public static FingerprintManagerCompat from(Context context) {
+ @NonNull
+ public static FingerprintManagerCompat from(@NonNull Context context) {
return new FingerprintManagerCompat(context);
}
@@ -119,8 +120,9 @@
}
}
+ @Nullable
@RequiresApi(23)
- private static FingerprintManager getFingerprintManagerOrNull(Context context) {
+ private static FingerprintManager getFingerprintManagerOrNull(@NonNull Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
return context.getSystemService(FingerprintManager.class);
} else {
@@ -195,20 +197,20 @@
private final Cipher mCipher;
private final Mac mMac;
- public CryptoObject(Signature signature) {
+ public CryptoObject(@NonNull Signature signature) {
mSignature = signature;
mCipher = null;
mMac = null;
}
- public CryptoObject(Cipher cipher) {
+ public CryptoObject(@NonNull Cipher cipher) {
mCipher = cipher;
mSignature = null;
mMac = null;
}
- public CryptoObject(Mac mac) {
+ public CryptoObject(@NonNull Mac mac) {
mMac = mac;
mCipher = null;
mSignature = null;
@@ -218,18 +220,21 @@
* Get {@link Signature} object.
* @return {@link Signature} object or null if this doesn't contain one.
*/
+ @Nullable
public Signature getSignature() { return mSignature; }
/**
* Get {@link Cipher} object.
* @return {@link Cipher} object or null if this doesn't contain one.
*/
+ @Nullable
public Cipher getCipher() { return mCipher; }
/**
* Get {@link Mac} object.
* @return {@link Mac} object or null if this doesn't contain one.
*/
+ @Nullable
public Mac getMac() { return mMac; }
}
diff --git a/compat/java/android/support/v4/net/ConnectivityManagerCompat.java b/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
index cdddb68..c08cac8 100644
--- a/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
+++ b/compat/java/android/support/v4/net/ConnectivityManagerCompat.java
@@ -32,6 +32,8 @@
import android.net.NetworkInfo;
import android.os.Build;
import android.support.annotation.IntDef;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.RequiresPermission;
import android.support.annotation.RestrictTo;
@@ -91,7 +93,7 @@
*/
@SuppressWarnings("deprecation")
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
- public static boolean isActiveNetworkMetered(ConnectivityManager cm) {
+ public static boolean isActiveNetworkMetered(@NonNull ConnectivityManager cm) {
if (Build.VERSION.SDK_INT >= 16) {
return cm.isActiveNetworkMetered();
} else {
@@ -128,8 +130,10 @@
* potentially-stale value from
* {@link ConnectivityManager#EXTRA_NETWORK_INFO}. May be {@code null}.
*/
+ @Nullable
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
- public static NetworkInfo getNetworkInfoFromBroadcast(ConnectivityManager cm, Intent intent) {
+ public static NetworkInfo getNetworkInfoFromBroadcast(@NonNull ConnectivityManager cm,
+ @NonNull Intent intent) {
final NetworkInfo info = intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
if (info != null) {
return cm.getNetworkInfo(info.getType());
@@ -147,7 +151,7 @@
* or {@link #RESTRICT_BACKGROUND_STATUS_WHITELISTED}
*/
@RestrictBackgroundStatus
- public static int getRestrictBackgroundStatus(ConnectivityManager cm) {
+ public static int getRestrictBackgroundStatus(@NonNull ConnectivityManager cm) {
if (Build.VERSION.SDK_INT >= 24) {
return cm.getRestrictBackgroundStatus();
} else {
diff --git a/compat/java/android/support/v4/net/TrafficStatsCompat.java b/compat/java/android/support/v4/net/TrafficStatsCompat.java
index 1049fa5..b74b8d0 100644
--- a/compat/java/android/support/v4/net/TrafficStatsCompat.java
+++ b/compat/java/android/support/v4/net/TrafficStatsCompat.java
@@ -19,6 +19,7 @@
import android.net.TrafficStats;
import android.os.Build;
import android.os.ParcelFileDescriptor;
+import android.support.annotation.NonNull;
import java.net.DatagramSocket;
import java.net.Socket;
@@ -131,7 +132,7 @@
*
* @see #setThreadStatsTag(int)
*/
- public static void tagDatagramSocket(DatagramSocket socket) throws SocketException {
+ public static void tagDatagramSocket(@NonNull DatagramSocket socket) throws SocketException {
if (Build.VERSION.SDK_INT >= 24) {
TrafficStats.tagDatagramSocket(socket);
} else {
@@ -148,7 +149,7 @@
/**
* Remove any statistics parameters from the given {@link DatagramSocket}.
*/
- public static void untagDatagramSocket(DatagramSocket socket) throws SocketException {
+ public static void untagDatagramSocket(@NonNull DatagramSocket socket) throws SocketException {
if (Build.VERSION.SDK_INT >= 24) {
TrafficStats.untagDatagramSocket(socket);
} else {
diff --git a/compat/java/android/support/v4/provider/FontRequest.java b/compat/java/android/support/v4/provider/FontRequest.java
index cb32f06..b14f85e 100644
--- a/compat/java/android/support/v4/provider/FontRequest.java
+++ b/compat/java/android/support/v4/provider/FontRequest.java
@@ -89,6 +89,7 @@
* Returns the selected font provider's authority. This tells the system what font provider
* it should request the font from.
*/
+ @NonNull
public String getProviderAuthority() {
return mProviderAuthority;
}
@@ -97,6 +98,7 @@
* Returns the selected font provider's package. This helps the system verify that the provider
* identified by the given authority is the one requested.
*/
+ @NonNull
public String getProviderPackage() {
return mProviderPackage;
}
@@ -105,6 +107,7 @@
* Returns the query string. Refer to your font provider's documentation on the format of this
* string.
*/
+ @NonNull
public String getQuery() {
return mQuery;
}
diff --git a/compat/java/android/support/v4/provider/FontsContractCompat.java b/compat/java/android/support/v4/provider/FontsContractCompat.java
index 6ad46a1..3511f3a 100644
--- a/compat/java/android/support/v4/provider/FontsContractCompat.java
+++ b/compat/java/android/support/v4/provider/FontsContractCompat.java
@@ -600,6 +600,7 @@
* @param fonts An array of {@link FontInfo} to be used to create a Typeface.
* @return A Typeface object. Returns null if typeface creation fails.
*/
+ @Nullable
public static Typeface buildTypeface(@NonNull Context context,
@Nullable CancellationSignal cancellationSignal, @NonNull FontInfo[] fonts) {
return TypefaceCompat.createFromFontInfo(context, cancellationSignal, fonts,
diff --git a/compat/java/android/support/v4/util/AtomicFile.java b/compat/java/android/support/v4/util/AtomicFile.java
index 275f4e2..aefe705 100644
--- a/compat/java/android/support/v4/util/AtomicFile.java
+++ b/compat/java/android/support/v4/util/AtomicFile.java
@@ -16,6 +16,8 @@
package android.support.v4.util;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.util.Log;
import java.io.File;
@@ -48,7 +50,7 @@
* Create a new AtomicFile for a file located at the given File path.
* The secondary backup file will be the same file path with ".bak" appended.
*/
- public AtomicFile(File baseName) {
+ public AtomicFile(@NonNull File baseName) {
mBaseName = baseName;
mBackupName = new File(baseName.getPath() + ".bak");
}
@@ -57,6 +59,7 @@
* Return the path to the base file. You should not generally use this,
* as the data at that path may not be valid.
*/
+ @NonNull
public File getBaseFile() {
return mBaseName;
}
@@ -83,6 +86,7 @@
* safe (or will be lost). You must do your own threading protection for
* access to AtomicFile.
*/
+ @NonNull
public FileOutputStream startWrite() throws IOException {
// Rename the current file so it may be used as a backup during the next read
if (mBaseName.exists()) {
@@ -95,7 +99,7 @@
mBaseName.delete();
}
}
- FileOutputStream str = null;
+ FileOutputStream str;
try {
str = new FileOutputStream(mBaseName);
} catch (FileNotFoundException e) {
@@ -118,7 +122,7 @@
* commit the new data. The next attempt to read the atomic file
* will return the new file stream.
*/
- public void finishWrite(FileOutputStream str) {
+ public void finishWrite(@Nullable FileOutputStream str) {
if (str != null) {
sync(str);
try {
@@ -135,7 +139,7 @@
* returned by {@link #startWrite()}. This will close the current
* write stream, and roll back to the previous state of the file.
*/
- public void failWrite(FileOutputStream str) {
+ public void failWrite(@Nullable FileOutputStream str) {
if (str != null) {
sync(str);
try {
@@ -160,6 +164,7 @@
* be dropped. You must do your own threading protection for access to
* AtomicFile.
*/
+ @NonNull
public FileInputStream openRead() throws FileNotFoundException {
if (mBackupName.exists()) {
mBaseName.delete();
@@ -172,6 +177,7 @@
* A convenience for {@link #openRead()} that also reads all of the
* file contents into a byte array which is returned.
*/
+ @NonNull
public byte[] readFully() throws IOException {
FileInputStream stream = openRead();
try {
@@ -200,11 +206,9 @@
}
}
- static boolean sync(FileOutputStream stream) {
+ private static boolean sync(@NonNull FileOutputStream stream) {
try {
- if (stream != null) {
- stream.getFD().sync();
- }
+ stream.getFD().sync();
return true;
} catch (IOException e) {
}
diff --git a/compat/java/android/support/v4/util/ObjectsCompat.java b/compat/java/android/support/v4/util/ObjectsCompat.java
index 4650060..b6c740e 100644
--- a/compat/java/android/support/v4/util/ObjectsCompat.java
+++ b/compat/java/android/support/v4/util/ObjectsCompat.java
@@ -16,6 +16,7 @@
package android.support.v4.util;
import android.os.Build;
+import android.support.annotation.Nullable;
import java.util.Objects;
@@ -43,7 +44,7 @@
* and {@code false} otherwise
* @see Object#equals(Object)
*/
- public static boolean equals(Object a, Object b) {
+ public static boolean equals(@Nullable Object a, @Nullable Object b) {
if (Build.VERSION.SDK_INT >= 19) {
return Objects.equals(a, b);
} else {
diff --git a/compat/java/android/support/v4/util/Pair.java b/compat/java/android/support/v4/util/Pair.java
index 46ea5cd..9047aec 100644
--- a/compat/java/android/support/v4/util/Pair.java
+++ b/compat/java/android/support/v4/util/Pair.java
@@ -16,14 +16,17 @@
package android.support.v4.util;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
/**
* Container to ease passing around a tuple of two objects. This object provides a sensible
* implementation of equals(), returning true if equals() is true on each of the contained
* objects.
*/
public class Pair<F, S> {
- public final F first;
- public final S second;
+ public final @Nullable F first;
+ public final @Nullable S second;
/**
* Constructor for a Pair.
@@ -31,7 +34,7 @@
* @param first the first object in the Pair
* @param second the second object in the pair
*/
- public Pair(F first, S second) {
+ public Pair(@Nullable F first, @Nullable S second) {
this.first = first;
this.second = second;
}
@@ -78,7 +81,8 @@
* @param b the second object in the pair
* @return a Pair that is templatized with the types of a and b
*/
- public static <A, B> Pair <A, B> create(A a, B b) {
+ @NonNull
+ public static <A, B> Pair <A, B> create(@Nullable A a, @Nullable B b) {
return new Pair<A, B>(a, b);
}
}
diff --git a/compat/java/android/support/v4/util/Pools.java b/compat/java/android/support/v4/util/Pools.java
index 6882660..99fd888 100644
--- a/compat/java/android/support/v4/util/Pools.java
+++ b/compat/java/android/support/v4/util/Pools.java
@@ -18,6 +18,9 @@
package android.support.v4.util;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
/**
* Helper class for creating pools of objects. An example use looks like this:
* <pre>
@@ -53,6 +56,7 @@
/**
* @return An instance from the pool if such, null otherwise.
*/
+ @Nullable
public T acquire();
/**
@@ -63,7 +67,7 @@
*
* @throws IllegalStateException If the instance is already in the pool.
*/
- public boolean release(T instance);
+ public boolean release(@NonNull T instance);
}
private Pools() {
@@ -108,7 +112,7 @@
}
@Override
- public boolean release(T instance) {
+ public boolean release(@NonNull T instance) {
if (isInPool(instance)) {
throw new IllegalStateException("Already in the pool!");
}
@@ -120,7 +124,7 @@
return false;
}
- private boolean isInPool(T instance) {
+ private boolean isInPool(@NonNull T instance) {
for (int i = 0; i < mPoolSize; i++) {
if (mPool[i] == instance) {
return true;
@@ -157,7 +161,7 @@
}
@Override
- public boolean release(T element) {
+ public boolean release(@NonNull T element) {
synchronized (mLock) {
return super.release(element);
}
diff --git a/compat/java/android/support/v4/widget/EdgeEffectCompat.java b/compat/java/android/support/v4/widget/EdgeEffectCompat.java
index 9293e60..0d370a8 100644
--- a/compat/java/android/support/v4/widget/EdgeEffectCompat.java
+++ b/compat/java/android/support/v4/widget/EdgeEffectCompat.java
@@ -18,6 +18,7 @@
import android.content.Context;
import android.graphics.Canvas;
import android.os.Build;
+import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.widget.EdgeEffect;
@@ -170,7 +171,8 @@
*
* @see {@link EdgeEffect#onPull(float, float)}
*/
- public static void onPull(EdgeEffect edgeEffect, float deltaDistance, float displacement) {
+ public static void onPull(@NonNull EdgeEffect edgeEffect, float deltaDistance,
+ float displacement) {
IMPL.onPull(edgeEffect, deltaDistance, displacement);
}
diff --git a/compat/java/android/support/v4/widget/ImageViewCompat.java b/compat/java/android/support/v4/widget/ImageViewCompat.java
index acaaf63..b517de5 100644
--- a/compat/java/android/support/v4/widget/ImageViewCompat.java
+++ b/compat/java/android/support/v4/widget/ImageViewCompat.java
@@ -20,6 +20,8 @@
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.widget.ImageView;
@@ -130,21 +132,24 @@
/**
* Return the tint applied to the image drawable, if specified.
*/
- public static ColorStateList getImageTintList(ImageView view) {
+ @Nullable
+ public static ColorStateList getImageTintList(@NonNull ImageView view) {
return IMPL.getImageTintList(view);
}
/**
* Applies a tint to the image drawable.
*/
- public static void setImageTintList(ImageView view, ColorStateList tintList) {
+ public static void setImageTintList(@NonNull ImageView view,
+ @Nullable ColorStateList tintList) {
IMPL.setImageTintList(view, tintList);
}
/**
* Return the blending mode used to apply the tint to the image drawable, if specified.
*/
- public static PorterDuff.Mode getImageTintMode(ImageView view) {
+ @Nullable
+ public static PorterDuff.Mode getImageTintMode(@NonNull ImageView view) {
return IMPL.getImageTintMode(view);
}
@@ -153,7 +158,7 @@
* {@link #setImageTintList(android.widget.ImageView, android.content.res.ColorStateList)}
* to the image drawable. The default mode is {@link PorterDuff.Mode#SRC_IN}.
*/
- public static void setImageTintMode(ImageView view, PorterDuff.Mode mode) {
+ public static void setImageTintMode(@NonNull ImageView view, @Nullable PorterDuff.Mode mode) {
IMPL.setImageTintMode(view, mode);
}
diff --git a/compat/java/android/support/v4/widget/ListPopupWindowCompat.java b/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
index ab86e58..4532733 100644
--- a/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
+++ b/compat/java/android/support/v4/widget/ListPopupWindowCompat.java
@@ -17,6 +17,8 @@
package android.support.v4.widget;
import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.ListPopupWindow;
@@ -88,8 +90,9 @@
* @return a touch listener that controls drag-to-open behavior, or {@code null} on
* unsupported APIs
*/
+ @Nullable
public static OnTouchListener createDragToOpenListener(
- ListPopupWindow listPopupWindow, View src) {
+ @NonNull ListPopupWindow listPopupWindow, @NonNull View src) {
if (Build.VERSION.SDK_INT >= 19) {
return listPopupWindow.createDragToOpenListener(src);
} else {
diff --git a/compat/java/android/support/v4/widget/PopupMenuCompat.java b/compat/java/android/support/v4/widget/PopupMenuCompat.java
index 639a84b..10c5ff3 100644
--- a/compat/java/android/support/v4/widget/PopupMenuCompat.java
+++ b/compat/java/android/support/v4/widget/PopupMenuCompat.java
@@ -17,6 +17,8 @@
package android.support.v4.widget;
import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.view.View.OnTouchListener;
import android.widget.PopupMenu;
@@ -47,7 +49,8 @@
* @return a touch listener that controls drag-to-open behavior, or {@code null} on
* unsupported APIs
*/
- public static OnTouchListener getDragToOpenListener(Object popupMenu) {
+ @Nullable
+ public static OnTouchListener getDragToOpenListener(@NonNull Object popupMenu) {
if (Build.VERSION.SDK_INT >= 19) {
return ((PopupMenu) popupMenu).getDragToOpenListener();
} else {
diff --git a/compat/java/android/support/v4/widget/PopupWindowCompat.java b/compat/java/android/support/v4/widget/PopupWindowCompat.java
index d846b40..d9de3db 100644
--- a/compat/java/android/support/v4/widget/PopupWindowCompat.java
+++ b/compat/java/android/support/v4/widget/PopupWindowCompat.java
@@ -17,6 +17,7 @@
package android.support.v4.widget;
import android.os.Build;
+import android.support.annotation.NonNull;
import android.support.annotation.RequiresApi;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat;
@@ -213,8 +214,8 @@
* @param yoff A vertical offset from the anchor in pixels
* @param gravity Alignment of the popup relative to the anchor
*/
- public static void showAsDropDown(PopupWindow popup, View anchor, int xoff, int yoff,
- int gravity) {
+ public static void showAsDropDown(@NonNull PopupWindow popup, @NonNull View anchor,
+ int xoff, int yoff, int gravity) {
IMPL.showAsDropDown(popup, anchor, xoff, yoff, gravity);
}
@@ -224,7 +225,7 @@
*
* @param overlapAnchor Whether the popup should overlap its anchor.
*/
- public static void setOverlapAnchor(PopupWindow popupWindow, boolean overlapAnchor) {
+ public static void setOverlapAnchor(@NonNull PopupWindow popupWindow, boolean overlapAnchor) {
IMPL.setOverlapAnchor(popupWindow, overlapAnchor);
}
@@ -234,7 +235,7 @@
*
* @return Whether the popup should overlap its anchor.
*/
- public static boolean getOverlapAnchor(PopupWindow popupWindow) {
+ public static boolean getOverlapAnchor(@NonNull PopupWindow popupWindow) {
return IMPL.getOverlapAnchor(popupWindow);
}
@@ -247,7 +248,7 @@
*
* @see android.view.WindowManager.LayoutParams#type
*/
- public static void setWindowLayoutType(PopupWindow popupWindow, int layoutType) {
+ public static void setWindowLayoutType(@NonNull PopupWindow popupWindow, int layoutType) {
IMPL.setWindowLayoutType(popupWindow, layoutType);
}
@@ -256,7 +257,7 @@
*
* @see #setWindowLayoutType(PopupWindow popupWindow, int)
*/
- public static int getWindowLayoutType(PopupWindow popupWindow) {
+ public static int getWindowLayoutType(@NonNull PopupWindow popupWindow) {
return IMPL.getWindowLayoutType(popupWindow);
}
}
diff --git a/compat/java/android/support/v4/widget/TextViewCompat.java b/compat/java/android/support/v4/widget/TextViewCompat.java
index 8d9e4ab..dc87a38 100644
--- a/compat/java/android/support/v4/widget/TextViewCompat.java
+++ b/compat/java/android/support/v4/widget/TextViewCompat.java
@@ -479,6 +479,7 @@
/**
* Returns drawables for the start, top, end, and bottom borders from the given text view.
*/
+ @NonNull
public static Drawable[] getCompoundDrawablesRelative(@NonNull TextView textView) {
return IMPL.getCompoundDrawablesRelative(textView);
}
@@ -493,7 +494,8 @@
*
* @attr name android:autoSizeTextType
*/
- public static void setAutoSizeTextTypeWithDefaults(TextView textView, int autoSizeTextType) {
+ public static void setAutoSizeTextTypeWithDefaults(@NonNull TextView textView,
+ int autoSizeTextType) {
IMPL.setAutoSizeTextTypeWithDefaults(textView, autoSizeTextType);
}
@@ -519,7 +521,7 @@
* @attr name android:autoSizeStepGranularity
*/
public static void setAutoSizeTextTypeUniformWithConfiguration(
- TextView textView,
+ @NonNull TextView textView,
int autoSizeMinTextSize,
int autoSizeMaxTextSize,
int autoSizeStepGranularity,
@@ -542,7 +544,7 @@
* @attr name android:autoSizeTextType
* @attr name android:autoSizePresetSizes
*/
- public static void setAutoSizeTextTypeUniformWithPresetSizes(TextView textView,
+ public static void setAutoSizeTextTypeUniformWithPresetSizes(@NonNull TextView textView,
@NonNull int[] presetSizes, int unit) throws IllegalArgumentException {
IMPL.setAutoSizeTextTypeUniformWithPresetSizes(textView, presetSizes, unit);
}
@@ -556,7 +558,7 @@
*
* @attr name android:autoSizeTextType
*/
- public static int getAutoSizeTextType(TextView textView) {
+ public static int getAutoSizeTextType(@NonNull TextView textView) {
return IMPL.getAutoSizeTextType(textView);
}
@@ -565,7 +567,7 @@
*
* @attr name android:autoSizeStepGranularity
*/
- public static int getAutoSizeStepGranularity(TextView textView) {
+ public static int getAutoSizeStepGranularity(@NonNull TextView textView) {
return IMPL.getAutoSizeStepGranularity(textView);
}
@@ -575,7 +577,7 @@
*
* @attr name android:autoSizeMinTextSize
*/
- public static int getAutoSizeMinTextSize(TextView textView) {
+ public static int getAutoSizeMinTextSize(@NonNull TextView textView) {
return IMPL.getAutoSizeMinTextSize(textView);
}
@@ -585,7 +587,7 @@
*
* @attr name android:autoSizeMaxTextSize
*/
- public static int getAutoSizeMaxTextSize(TextView textView) {
+ public static int getAutoSizeMaxTextSize(@NonNull TextView textView) {
return IMPL.getAutoSizeMaxTextSize(textView);
}
@@ -594,7 +596,8 @@
*
* @attr name android:autoSizePresetSizes
*/
- public static int[] getAutoSizeTextAvailableSizes(TextView textView) {
+ @NonNull
+ public static int[] getAutoSizeTextAvailableSizes(@NonNull TextView textView) {
return IMPL.getAutoSizeTextAvailableSizes(textView);
}
}
diff --git a/core-utils/Android.mk b/core-utils/Android.mk
index 6dda862..a6855fc 100644
--- a/core-utils/Android.mk
+++ b/core-utils/Android.mk
@@ -27,9 +27,7 @@
LOCAL_MODULE := android-support-core-utils
LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
LOCAL_SRC_FILES := \
- $(call all-java-files-under,kitkat) \
- $(call all-java-files-under,api21) \
- $(call all-java-files-under,java)
+ $(call all-java-files-under,src/main/java)
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
LOCAL_SHARED_ANDROID_LIBRARIES := \
android-support-compat \
diff --git a/core-utils/build.gradle b/core-utils/build.gradle
index 29fe86c..55fe2bb 100644
--- a/core-utils/build.gradle
+++ b/core-utils/build.gradle
@@ -14,14 +14,6 @@
defaultConfig {
minSdkVersion 14
}
-
- sourceSets {
- main.java.srcDirs = [
- 'kitkat',
- 'api21',
- 'java'
- ]
- }
}
supportLibrary {
diff --git a/core-utils/java/android/support/v4/app/AppLaunchChecker.java b/core-utils/src/main/java/android/support/v4/app/AppLaunchChecker.java
similarity index 100%
rename from core-utils/java/android/support/v4/app/AppLaunchChecker.java
rename to core-utils/src/main/java/android/support/v4/app/AppLaunchChecker.java
diff --git a/core-utils/java/android/support/v4/app/FrameMetricsAggregator.java b/core-utils/src/main/java/android/support/v4/app/FrameMetricsAggregator.java
similarity index 100%
rename from core-utils/java/android/support/v4/app/FrameMetricsAggregator.java
rename to core-utils/src/main/java/android/support/v4/app/FrameMetricsAggregator.java
diff --git a/core-utils/java/android/support/v4/app/NavUtils.java b/core-utils/src/main/java/android/support/v4/app/NavUtils.java
similarity index 100%
rename from core-utils/java/android/support/v4/app/NavUtils.java
rename to core-utils/src/main/java/android/support/v4/app/NavUtils.java
diff --git a/core-utils/java/android/support/v4/app/TaskStackBuilder.java b/core-utils/src/main/java/android/support/v4/app/TaskStackBuilder.java
similarity index 100%
rename from core-utils/java/android/support/v4/app/TaskStackBuilder.java
rename to core-utils/src/main/java/android/support/v4/app/TaskStackBuilder.java
diff --git a/core-utils/java/android/support/v4/app/package.html b/core-utils/src/main/java/android/support/v4/app/package.html
similarity index 100%
rename from core-utils/java/android/support/v4/app/package.html
rename to core-utils/src/main/java/android/support/v4/app/package.html
diff --git a/core-utils/java/android/support/v4/content/AsyncTaskLoader.java b/core-utils/src/main/java/android/support/v4/content/AsyncTaskLoader.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/AsyncTaskLoader.java
rename to core-utils/src/main/java/android/support/v4/content/AsyncTaskLoader.java
diff --git a/core-utils/java/android/support/v4/content/CursorLoader.java b/core-utils/src/main/java/android/support/v4/content/CursorLoader.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/CursorLoader.java
rename to core-utils/src/main/java/android/support/v4/content/CursorLoader.java
diff --git a/core-utils/java/android/support/v4/content/FileProvider.java b/core-utils/src/main/java/android/support/v4/content/FileProvider.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/FileProvider.java
rename to core-utils/src/main/java/android/support/v4/content/FileProvider.java
diff --git a/core-utils/java/android/support/v4/content/Loader.java b/core-utils/src/main/java/android/support/v4/content/Loader.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/Loader.java
rename to core-utils/src/main/java/android/support/v4/content/Loader.java
diff --git a/core-utils/java/android/support/v4/content/LocalBroadcastManager.java b/core-utils/src/main/java/android/support/v4/content/LocalBroadcastManager.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/LocalBroadcastManager.java
rename to core-utils/src/main/java/android/support/v4/content/LocalBroadcastManager.java
diff --git a/core-utils/java/android/support/v4/content/MimeTypeFilter.java b/core-utils/src/main/java/android/support/v4/content/MimeTypeFilter.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/MimeTypeFilter.java
rename to core-utils/src/main/java/android/support/v4/content/MimeTypeFilter.java
diff --git a/core-utils/java/android/support/v4/content/ModernAsyncTask.java b/core-utils/src/main/java/android/support/v4/content/ModernAsyncTask.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/ModernAsyncTask.java
rename to core-utils/src/main/java/android/support/v4/content/ModernAsyncTask.java
diff --git a/core-utils/java/android/support/v4/content/PermissionChecker.java b/core-utils/src/main/java/android/support/v4/content/PermissionChecker.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/PermissionChecker.java
rename to core-utils/src/main/java/android/support/v4/content/PermissionChecker.java
diff --git a/core-utils/java/android/support/v4/content/WakefulBroadcastReceiver.java b/core-utils/src/main/java/android/support/v4/content/WakefulBroadcastReceiver.java
similarity index 100%
rename from core-utils/java/android/support/v4/content/WakefulBroadcastReceiver.java
rename to core-utils/src/main/java/android/support/v4/content/WakefulBroadcastReceiver.java
diff --git a/core-utils/java/android/support/v4/content/package.html b/core-utils/src/main/java/android/support/v4/content/package.html
similarity index 100%
rename from core-utils/java/android/support/v4/content/package.html
rename to core-utils/src/main/java/android/support/v4/content/package.html
diff --git a/core-utils/java/android/support/v4/graphics/ColorUtils.java b/core-utils/src/main/java/android/support/v4/graphics/ColorUtils.java
similarity index 100%
rename from core-utils/java/android/support/v4/graphics/ColorUtils.java
rename to core-utils/src/main/java/android/support/v4/graphics/ColorUtils.java
diff --git a/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java b/core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
similarity index 100%
rename from core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
rename to core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable.java
diff --git a/core-utils/api21/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java b/core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java
similarity index 100%
rename from core-utils/api21/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java
rename to core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawable21.java
diff --git a/core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java b/core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
similarity index 100%
rename from core-utils/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
rename to core-utils/src/main/java/android/support/v4/graphics/drawable/RoundedBitmapDrawableFactory.java
diff --git a/core-utils/java/android/support/v4/math/MathUtils.java b/core-utils/src/main/java/android/support/v4/math/MathUtils.java
similarity index 100%
rename from core-utils/java/android/support/v4/math/MathUtils.java
rename to core-utils/src/main/java/android/support/v4/math/MathUtils.java
diff --git a/core-utils/java/android/support/v4/print/PrintHelper.java b/core-utils/src/main/java/android/support/v4/print/PrintHelper.java
similarity index 100%
rename from core-utils/java/android/support/v4/print/PrintHelper.java
rename to core-utils/src/main/java/android/support/v4/print/PrintHelper.java
diff --git a/core-utils/java/android/support/v4/provider/DocumentFile.java b/core-utils/src/main/java/android/support/v4/provider/DocumentFile.java
similarity index 100%
rename from core-utils/java/android/support/v4/provider/DocumentFile.java
rename to core-utils/src/main/java/android/support/v4/provider/DocumentFile.java
diff --git a/core-utils/kitkat/android/support/v4/provider/DocumentsContractApi19.java b/core-utils/src/main/java/android/support/v4/provider/DocumentsContractApi19.java
similarity index 100%
rename from core-utils/kitkat/android/support/v4/provider/DocumentsContractApi19.java
rename to core-utils/src/main/java/android/support/v4/provider/DocumentsContractApi19.java
diff --git a/core-utils/java/android/support/v4/provider/RawDocumentFile.java b/core-utils/src/main/java/android/support/v4/provider/RawDocumentFile.java
similarity index 100%
rename from core-utils/java/android/support/v4/provider/RawDocumentFile.java
rename to core-utils/src/main/java/android/support/v4/provider/RawDocumentFile.java
diff --git a/core-utils/java/android/support/v4/provider/SingleDocumentFile.java b/core-utils/src/main/java/android/support/v4/provider/SingleDocumentFile.java
similarity index 100%
rename from core-utils/java/android/support/v4/provider/SingleDocumentFile.java
rename to core-utils/src/main/java/android/support/v4/provider/SingleDocumentFile.java
diff --git a/core-utils/java/android/support/v4/provider/TreeDocumentFile.java b/core-utils/src/main/java/android/support/v4/provider/TreeDocumentFile.java
similarity index 100%
rename from core-utils/java/android/support/v4/provider/TreeDocumentFile.java
rename to core-utils/src/main/java/android/support/v4/provider/TreeDocumentFile.java
diff --git a/customtabs/api/current.txt b/customtabs/api/current.txt
index 58cd212..05c16c1 100644
--- a/customtabs/api/current.txt
+++ b/customtabs/api/current.txt
@@ -6,6 +6,7 @@
method public void onMessageChannelReady(android.os.Bundle);
method public void onNavigationEvent(int, android.os.Bundle);
method public void onPostMessage(java.lang.String, android.os.Bundle);
+ method public void onRelationshipValidationResult(int, android.net.Uri, boolean, android.os.Bundle);
field public static final int NAVIGATION_ABORTED = 4; // 0x4
field public static final int NAVIGATION_FAILED = 3; // 0x3
field public static final int NAVIGATION_FINISHED = 2; // 0x2
@@ -88,15 +89,21 @@
method protected abstract int postMessage(android.support.customtabs.CustomTabsSessionToken, java.lang.String, android.os.Bundle);
method protected abstract boolean requestPostMessageChannel(android.support.customtabs.CustomTabsSessionToken, android.net.Uri);
method protected abstract boolean updateVisuals(android.support.customtabs.CustomTabsSessionToken, android.os.Bundle);
+ method protected abstract boolean validateRelationship(android.support.customtabs.CustomTabsSessionToken, int, android.net.Uri, android.os.Bundle);
method protected abstract boolean warmup(long);
field public static final java.lang.String ACTION_CUSTOM_TABS_CONNECTION = "android.support.customtabs.action.CustomTabsService";
field public static final java.lang.String KEY_URL = "android.support.customtabs.otherurls.URL";
+ field public static final int RELATION_HANDLE_ALL_URLS = 2; // 0x2
+ field public static final int RELATION_USE_AS_ORIGIN = 1; // 0x1
field public static final int RESULT_FAILURE_DISALLOWED = -1; // 0xffffffff
field public static final int RESULT_FAILURE_MESSAGING_ERROR = -3; // 0xfffffffd
field public static final int RESULT_FAILURE_REMOTE_ERROR = -2; // 0xfffffffe
field public static final int RESULT_SUCCESS = 0; // 0x0
}
+ public static abstract class CustomTabsService.Relation implements java.lang.annotation.Annotation {
+ }
+
public static abstract class CustomTabsService.Result implements java.lang.annotation.Annotation {
}
@@ -113,6 +120,7 @@
method public boolean setActionButton(android.graphics.Bitmap, java.lang.String);
method public boolean setSecondaryToolbarViews(android.widget.RemoteViews, int[], android.app.PendingIntent);
method public deprecated boolean setToolbarItem(int, android.graphics.Bitmap, java.lang.String);
+ method public boolean validateRelationship(int, android.net.Uri, android.os.Bundle);
}
public class CustomTabsSessionToken {
diff --git a/customtabs/src/android/support/customtabs/CustomTabsCallback.java b/customtabs/src/android/support/customtabs/CustomTabsCallback.java
index 818118a..f8d349a 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsCallback.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsCallback.java
@@ -16,7 +16,9 @@
package android.support.customtabs;
+import android.net.Uri;
import android.os.Bundle;
+import android.support.customtabs.CustomTabsService.Relation;
/**
* A callback class for custom tabs client to get messages regarding events in their custom tabs. In
@@ -98,4 +100,18 @@
* @param extras Reserved for future use.
*/
public void onPostMessage(String message, Bundle extras) {}
+
+ /**
+ * Called when a relationship validation result is available.
+ *
+ * @param relation Relation for which the result is available. Value previously passed to
+ * {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}. Must be one
+ * of the {@code CustomTabsService#RELATION_* } constants.
+ * @param requestedOrigin Origin requested. Value previously passed to
+ * {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}.
+ * @param result Whether the relation was validated.
+ * @param extras Reserved for future use.
+ */
+ public void onRelationshipValidationResult(@Relation int relation, Uri requestedOrigin,
+ boolean result, Bundle extras) {}
}
diff --git a/customtabs/src/android/support/customtabs/CustomTabsClient.java b/customtabs/src/android/support/customtabs/CustomTabsClient.java
index 09f3110..2e955cb 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsClient.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsClient.java
@@ -31,6 +31,7 @@
import android.os.RemoteException;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
+import android.support.customtabs.CustomTabsService.Relation;
import android.text.TextUtils;
import java.util.ArrayList;
@@ -234,6 +235,20 @@
}
});
}
+
+ @Override
+ public void onRelationshipValidationResult(
+ final @Relation int relation, final Uri requestedOrigin, final boolean result,
+ final @Nullable Bundle extras) throws RemoteException {
+ if (callback == null) return;
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onRelationshipValidationResult(
+ relation, requestedOrigin, result, extras);
+ }
+ });
+ }
};
try {
diff --git a/customtabs/src/android/support/customtabs/CustomTabsService.java b/customtabs/src/android/support/customtabs/CustomTabsService.java
index 5a940cf..aad174c 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsService.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsService.java
@@ -78,6 +78,23 @@
*/
public static final int RESULT_FAILURE_MESSAGING_ERROR = -3;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({RELATION_USE_AS_ORIGIN, RELATION_HANDLE_ALL_URLS})
+ public @interface Relation {
+ }
+
+ /**
+ * Used for {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}. For
+ * App -> Web transitions, requests the app to use the declared origin to be used as origin for
+ * the client app in the web APIs context.
+ */
+ public static final int RELATION_USE_AS_ORIGIN = 1;
+ /**
+ * Used for {@link CustomTabsSession#validateRelationship(int, Uri, Bundle)}. Requests the
+ * ability to handle all URLs from a given origin.
+ */
+ public static final int RELATION_HANDLE_ALL_URLS = 2;
+
private final Map<IBinder, DeathRecipient> mDeathRecipientMap = new ArrayMap<>();
private ICustomTabsService.Stub mBinder = new ICustomTabsService.Stub() {
@@ -137,6 +154,13 @@
return CustomTabsService.this.postMessage(
new CustomTabsSessionToken(callback), message, extras);
}
+
+ @Override
+ public boolean validateRelationship(
+ ICustomTabsCallback callback, @Relation int relation, Uri origin, Bundle extras) {
+ return CustomTabsService.this.validateRelationship(
+ new CustomTabsSessionToken(callback), relation, origin, extras);
+ }
};
@Override
@@ -268,4 +292,23 @@
@Result
protected abstract int postMessage(
CustomTabsSessionToken sessionToken, String message, Bundle extras);
+
+ /**
+ * Request to validate a relationship between the application and an origin.
+ *
+ * If this method returns true, the validation result will be provided through
+ * {@link CustomTabsCallback#onRelationshipValidationResult(int, Uri, boolean, Bundle)}.
+ * Otherwise the request didn't succeed. The client must call
+ * {@link CustomTabsClient#warmup(long)} before this.
+ *
+ * @param sessionToken The unique identifier for the session. Can not be null.
+ * @param relation Relation to check, must be one of the {@code CustomTabsService#RELATION_* }
+ * constants.
+ * @param origin Origin for the relation query.
+ * @param extras Reserved for future use.
+ * @return true if the request has been submitted successfully.
+ */
+ protected abstract boolean validateRelationship(
+ CustomTabsSessionToken sessionToken, @Relation int relation, Uri origin,
+ Bundle extras);
}
diff --git a/customtabs/src/android/support/customtabs/CustomTabsSession.java b/customtabs/src/android/support/customtabs/CustomTabsSession.java
index cad897c..d4930ae 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsSession.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsSession.java
@@ -25,6 +25,7 @@
import android.os.RemoteException;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import android.support.customtabs.CustomTabsService.Relation;
import android.support.customtabs.CustomTabsService.Result;
import android.view.View;
import android.widget.RemoteViews;
@@ -185,6 +186,39 @@
}
}
+ /**
+ * Requests to validate a relationship between the application and an origin.
+ *
+ * <p>
+ * See <a href="https://developers.google.com/digital-asset-links/v1/getting-started">here</a>
+ * for documentation about Digital Asset Links. This methods requests the browser to verify
+ * a relation with the calling application, to grant the associated rights.
+ *
+ * <p>
+ * If this method returns {@code true}, the validation result will be provided through
+ * {@link CustomTabsCallback#onRelationshipValidationResult(int, Uri, boolean, Bundle)}.
+ * Otherwise the request didn't succeed. The client must call
+ * {@link CustomTabsClient#warmup(long)} before this.
+ *
+ * @param relation Relation to check, must be one of the {@code CustomTabsService#RELATION_* }
+ * constants.
+ * @param origin Origin.
+ * @param extras Reserved for future use.
+ * @return {@code true} if the request has been submitted successfully.
+ */
+ public boolean validateRelationship(@Relation int relation, @NonNull Uri origin,
+ @Nullable Bundle extras) {
+ if (relation < CustomTabsService.RELATION_USE_AS_ORIGIN
+ || relation > CustomTabsService.RELATION_HANDLE_ALL_URLS) {
+ return false;
+ }
+ try {
+ return mService.validateRelationship(mCallback, relation, origin, extras);
+ } catch (RemoteException e) {
+ return false;
+ }
+ }
+
/* package */ IBinder getBinder() {
return mCallback.asBinder();
}
diff --git a/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java b/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java
index adfadd9..ee47278 100644
--- a/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java
+++ b/customtabs/src/android/support/customtabs/CustomTabsSessionToken.java
@@ -17,9 +17,11 @@
package android.support.customtabs;
import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.support.customtabs.CustomTabsService.Relation;
import android.support.v4.app.BundleCompat;
import android.util.Log;
@@ -85,6 +87,18 @@
Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
}
}
+
+ @Override
+ public void onRelationshipValidationResult(@Relation int relation, Uri origin,
+ boolean result, Bundle extras) {
+ try {
+ mCallbackBinder.onRelationshipValidationResult(
+ relation, origin, result, extras);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException during ICustomTabsCallback transaction");
+ }
+ }
+
};
}
diff --git a/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl b/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl
index 32b6e9b..3e2c48c 100644
--- a/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl
+++ b/customtabs/src/android/support/customtabs/ICustomTabsCallback.aidl
@@ -27,4 +27,5 @@
void extraCallback(String callbackName, in Bundle args) = 2;
void onMessageChannelReady(in Bundle extras) = 3;
void onPostMessage(String message, in Bundle extras) = 4;
+ void onRelationshipValidationResult(int relation, in Uri origin, boolean result, in Bundle extras) = 5;
}
diff --git a/customtabs/src/android/support/customtabs/ICustomTabsService.aidl b/customtabs/src/android/support/customtabs/ICustomTabsService.aidl
index b24b0dd..376c2a4 100644
--- a/customtabs/src/android/support/customtabs/ICustomTabsService.aidl
+++ b/customtabs/src/android/support/customtabs/ICustomTabsService.aidl
@@ -36,4 +36,5 @@
boolean updateVisuals(in ICustomTabsCallback callback, in Bundle bundle) = 5;
boolean requestPostMessageChannel(in ICustomTabsCallback callback, in Uri postMessageOrigin) = 6;
int postMessage(in ICustomTabsCallback callback, String message, in Bundle extras) = 7;
+ boolean validateRelationship(in ICustomTabsCallback callback, int relation, in Uri origin, in Bundle extras) = 8;
}
diff --git a/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java b/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java
index 56b1817..804d354 100644
--- a/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java
+++ b/customtabs/tests/src/android/support/customtabs/TestCustomTabsCallback.java
@@ -16,6 +16,7 @@
package android.support.customtabs;
+import android.net.Uri;
import android.os.Bundle;
import android.os.RemoteException;
@@ -50,6 +51,13 @@
throws RemoteException {
TestCustomTabsCallback.this.onPostMessage(message, extras);
}
+
+ @Override
+ public void onRelationshipValidationResult(int relation, Uri origin, boolean result,
+ Bundle extras) throws RemoteException {
+ TestCustomTabsCallback.this.onRelationshipValidationResult(
+ relation, origin, result, extras);
+ }
};
/* package */ ICustomTabsCallback getStub() {
diff --git a/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java b/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java
index b5c5e86..e3d5fa8 100644
--- a/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java
+++ b/customtabs/tests/src/android/support/customtabs/TestCustomTabsService.java
@@ -71,4 +71,10 @@
if (!mPostMessageRequested) return CustomTabsService.RESULT_FAILURE_DISALLOWED;
return CustomTabsService.RESULT_SUCCESS;
}
+
+ @Override
+ protected boolean validateRelationship(CustomTabsSessionToken sessionToken,
+ @Relation int relation, Uri origin, Bundle extras) {
+ return false;
+ }
}
diff --git a/emoji/appcompat/Android.mk b/emoji/appcompat/Android.mk
index 54f6b14..f04d158 100644
--- a/emoji/appcompat/Android.mk
+++ b/emoji/appcompat/Android.mk
@@ -29,7 +29,7 @@
LOCAL_USE_AAPT2 := true
LOCAL_MODULE := android-support-emoji-appcompat
LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
LOCAL_SHARED_ANDROID_LIBRARIES := \
android-support-annotations \
android-support-v7-appcompat \
diff --git a/emoji/appcompat/build.gradle b/emoji/appcompat/build.gradle
index 9b6e0d4..e22000c 100644
--- a/emoji/appcompat/build.gradle
+++ b/emoji/appcompat/build.gradle
@@ -26,10 +26,6 @@
defaultConfig {
minSdkVersion 14
}
-
- sourceSets {
- main.java.srcDir 'src'
- }
}
supportLibrary {
diff --git a/emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatButton.java b/emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatButton.java
similarity index 100%
rename from emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatButton.java
rename to emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatButton.java
diff --git a/emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatEditText.java b/emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatEditText.java
similarity index 100%
rename from emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatEditText.java
rename to emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatEditText.java
diff --git a/emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatTextView.java b/emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatTextView.java
similarity index 100%
rename from emoji/appcompat/src/android/support/text/emoji/widget/EmojiAppCompatTextView.java
rename to emoji/appcompat/src/main/java/android/support/text/emoji/widget/EmojiAppCompatTextView.java
diff --git a/emoji/bundled/Android.mk b/emoji/bundled/Android.mk
index 3b6b181..29f0d58 100644
--- a/emoji/bundled/Android.mk
+++ b/emoji/bundled/Android.mk
@@ -28,7 +28,7 @@
LOCAL_USE_AAPT2 := true
LOCAL_MODULE := android-support-emoji-bundled
LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
LOCAL_SHARED_ANDROID_LIBRARIES := \
android-support-annotations \
android-support-emoji \
diff --git a/emoji/bundled/build.gradle b/emoji/bundled/build.gradle
index b882ee1..766d165 100644
--- a/emoji/bundled/build.gradle
+++ b/emoji/bundled/build.gradle
@@ -10,7 +10,6 @@
}
sourceSets {
- main.java.srcDir 'src'
main.assets.srcDirs new File(fontDir, "font").getAbsolutePath()
}
}
diff --git a/emoji/bundled/src/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java b/emoji/bundled/src/main/java/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
similarity index 100%
rename from emoji/bundled/src/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
rename to emoji/bundled/src/main/java/android/support/text/emoji/bundled/BundledEmojiCompatConfig.java
diff --git a/emoji/core/Android.mk b/emoji/core/Android.mk
index 774ba29..8b7a032 100644
--- a/emoji/core/Android.mk
+++ b/emoji/core/Android.mk
@@ -27,8 +27,8 @@
LOCAL_USE_AAPT2 := true
LOCAL_MODULE := android-support-emoji
LOCAL_SDK_VERSION := $(SUPPORT_CURRENT_SDK_VERSION)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+LOCAL_SRC_FILES := $(call all-java-files-under, src/main/java)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/src/main/res
LOCAL_STATIC_JAVA_LIBRARIES := \
noto-emoji-compat-java
LOCAL_SHARED_ANDROID_LIBRARIES := \
diff --git a/emoji/core/build.gradle b/emoji/core/build.gradle
index c0881d2..b4cd3fc 100644
--- a/emoji/core/build.gradle
+++ b/emoji/core/build.gradle
@@ -29,10 +29,7 @@
}
sourceSets {
- main.java {
- srcDirs = ['src']
- }
- main.res.srcDirs = ['res', 'res-public']
+ main.res.srcDirs += 'src/main/res-public'
main.resources {
srcDirs = [fontDir.getAbsolutePath()]
includes = ["LICENSE_UNICODE", "LICENSE_OFL"]
diff --git a/emoji/core/src/android/support/text/emoji/EmojiCompat.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/EmojiCompat.java
rename to emoji/core/src/main/java/android/support/text/emoji/EmojiCompat.java
diff --git a/emoji/core/src/android/support/text/emoji/EmojiMetadata.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiMetadata.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/EmojiMetadata.java
rename to emoji/core/src/main/java/android/support/text/emoji/EmojiMetadata.java
diff --git a/emoji/core/src/android/support/text/emoji/EmojiProcessor.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiProcessor.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/EmojiProcessor.java
rename to emoji/core/src/main/java/android/support/text/emoji/EmojiProcessor.java
diff --git a/emoji/core/src/android/support/text/emoji/EmojiSpan.java b/emoji/core/src/main/java/android/support/text/emoji/EmojiSpan.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/EmojiSpan.java
rename to emoji/core/src/main/java/android/support/text/emoji/EmojiSpan.java
diff --git a/emoji/core/src/android/support/text/emoji/FontRequestEmojiCompatConfig.java b/emoji/core/src/main/java/android/support/text/emoji/FontRequestEmojiCompatConfig.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/FontRequestEmojiCompatConfig.java
rename to emoji/core/src/main/java/android/support/text/emoji/FontRequestEmojiCompatConfig.java
diff --git a/emoji/core/src/android/support/text/emoji/MetadataListReader.java b/emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/MetadataListReader.java
rename to emoji/core/src/main/java/android/support/text/emoji/MetadataListReader.java
diff --git a/emoji/core/src/android/support/text/emoji/MetadataRepo.java b/emoji/core/src/main/java/android/support/text/emoji/MetadataRepo.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/MetadataRepo.java
rename to emoji/core/src/main/java/android/support/text/emoji/MetadataRepo.java
diff --git a/emoji/core/src/android/support/text/emoji/TypefaceEmojiSpan.java b/emoji/core/src/main/java/android/support/text/emoji/TypefaceEmojiSpan.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/TypefaceEmojiSpan.java
rename to emoji/core/src/main/java/android/support/text/emoji/TypefaceEmojiSpan.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EditTextAttributeHelper.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EditTextAttributeHelper.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EditTextAttributeHelper.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EditTextAttributeHelper.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiButton.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiButton.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiButton.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiButton.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiEditText.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditText.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiEditText.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditText.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiEditTextHelper.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditTextHelper.java
similarity index 96%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiEditTextHelper.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditTextHelper.java
index edc511f..a999e34 100644
--- a/emoji/core/src/android/support/text/emoji/widget/EmojiEditTextHelper.java
+++ b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditTextHelper.java
@@ -20,6 +20,7 @@
import android.os.Build;
import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.annotation.RestrictTo;
import android.support.text.emoji.EmojiCompat;
@@ -130,7 +131,8 @@
/**
* Updates the InputConnection with emoji support. Should be called from {@link
* TextView#onCreateInputConnection(EditorInfo)}. When used on devices running API 18 or below,
- * this method returns {@code inputConnection} that is given as a parameter.
+ * this method returns {@code inputConnection} that is given as a parameter. If
+ * {@code inputConnection} is {@code null}, returns {@code null}.
*
* @param inputConnection InputConnection instance created by TextView
* @param outAttrs EditorInfo passed into
@@ -138,10 +140,10 @@
*
* @return a new InputConnection instance that wraps {@code inputConnection}
*/
- @NonNull
- public InputConnection onCreateInputConnection(@NonNull final InputConnection inputConnection,
+ @Nullable
+ public InputConnection onCreateInputConnection(@Nullable final InputConnection inputConnection,
@NonNull final EditorInfo outAttrs) {
- Preconditions.checkNotNull(inputConnection, "inputConnection cannot be null");
+ if (inputConnection == null) return null;
return mHelper.onCreateInputConnection(inputConnection, outAttrs);
}
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiEditableFactory.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditableFactory.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiEditableFactory.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiEditableFactory.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiExtractEditText.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiExtractEditText.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiExtractEditText.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiExtractEditText.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiExtractTextLayout.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiExtractTextLayout.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiExtractTextLayout.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiExtractTextLayout.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiInputConnection.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiInputConnection.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiInputConnection.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiInputConnection.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiInputFilter.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiInputFilter.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiInputFilter.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiInputFilter.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiKeyListener.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiKeyListener.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiKeyListener.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiKeyListener.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTextView.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextView.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiTextView.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextView.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTextViewHelper.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextViewHelper.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiTextViewHelper.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextViewHelper.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTextWatcher.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextWatcher.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiTextWatcher.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTextWatcher.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/EmojiTransformationMethod.java b/emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTransformationMethod.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/EmojiTransformationMethod.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/EmojiTransformationMethod.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/ExtractButtonCompat.java b/emoji/core/src/main/java/android/support/text/emoji/widget/ExtractButtonCompat.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/ExtractButtonCompat.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/ExtractButtonCompat.java
diff --git a/emoji/core/src/android/support/text/emoji/widget/SpannableBuilder.java b/emoji/core/src/main/java/android/support/text/emoji/widget/SpannableBuilder.java
similarity index 100%
rename from emoji/core/src/android/support/text/emoji/widget/SpannableBuilder.java
rename to emoji/core/src/main/java/android/support/text/emoji/widget/SpannableBuilder.java
diff --git a/emoji/core/res-public/values/public_attrs.xml b/emoji/core/src/main/res-public/values/public_attrs.xml
similarity index 100%
rename from emoji/core/res-public/values/public_attrs.xml
rename to emoji/core/src/main/res-public/values/public_attrs.xml
diff --git a/emoji/core/res/layout/input_method_extract_view.xml b/emoji/core/src/main/res/layout/input_method_extract_view.xml
similarity index 100%
rename from emoji/core/res/layout/input_method_extract_view.xml
rename to emoji/core/src/main/res/layout/input_method_extract_view.xml
diff --git a/emoji/core/res/values/attrs.xml b/emoji/core/src/main/res/values/attrs.xml
similarity index 100%
rename from emoji/core/res/values/attrs.xml
rename to emoji/core/src/main/res/values/attrs.xml
diff --git a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperPre19Test.java b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperPre19Test.java
index d2bd722..0756fa2 100644
--- a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperPre19Test.java
+++ b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperPre19Test.java
@@ -16,6 +16,7 @@
package android.support.text.emoji.widget;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
@@ -28,6 +29,7 @@
import android.support.test.runner.AndroidJUnit4;
import android.text.TextWatcher;
import android.text.method.KeyListener;
+import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;
@@ -61,12 +63,28 @@
public void testGetOnCreateInputConnection_returnsSameInputConnection() {
final InputConnection param = mock(InputConnection.class);
final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(param,
+ new EditorInfo());
+
+ assertSame(param, inputConnection);
+ }
+
+ @Test
+ public void testGetOnCreateInputConnection_withNullAttrs_returnsSameInputConnection() {
+ final InputConnection param = mock(InputConnection.class);
+ final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(param,
null);
assertSame(param, inputConnection);
}
@Test
+ public void testGetOnCreateInputConnection_withNullInputConnection_returnsNull() {
+ final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(null,
+ new EditorInfo());
+ assertNull(inputConnection);
+ }
+
+ @Test
public void testDoesNotAttachTextWatcher() {
final EditText editText = mock(EditText.class);
diff --git a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperTest.java b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperTest.java
index efc7ca0..626bca1 100644
--- a/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperTest.java
+++ b/emoji/core/tests/java/android/support/text/emoji/widget/EmojiEditTextHelperTest.java
@@ -16,8 +16,11 @@
package android.support.text.emoji.widget;
+import static junit.framework.Assert.assertNotNull;
+
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
@@ -32,6 +35,7 @@
import android.support.text.emoji.EmojiCompat;
import android.text.TextWatcher;
import android.text.method.KeyListener;
+import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
import android.widget.EditText;
@@ -76,16 +80,26 @@
assertSame(keyListener1, keyListener2);
}
- @Test(expected = NullPointerException.class)
- public void testGetOnCreateInputConnection_withNull_throwsException() {
- mEmojiEditTextHelper.onCreateInputConnection(null, null);
+ @Test
+ public void testGetOnCreateInputConnection_withNullAttrs_returnsInputConnection() {
+ final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(
+ mock(InputConnection.class), null);
+ assertNotNull(inputConnection);
+ assertThat(inputConnection, instanceOf(EmojiInputConnection.class));
+ }
+
+ @Test
+ public void testGetOnCreateInputConnection_withNullInputConnection_returnsNull() {
+ InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(null,
+ new EditorInfo());
+ assertNull(inputConnection);
}
@Test
public void testGetOnCreateInputConnection_returnsEmojiInputConnection() {
final InputConnection inputConnection = mEmojiEditTextHelper.onCreateInputConnection(
mock(InputConnection.class), null);
-
+ assertNotNull(inputConnection);
assertThat(inputConnection, instanceOf(EmojiInputConnection.class));
}
diff --git a/fragment/java/android/support/v4/app/Fragment.java b/fragment/java/android/support/v4/app/Fragment.java
index ba74521..0eb7083 100644
--- a/fragment/java/android/support/v4/app/Fragment.java
+++ b/fragment/java/android/support/v4/app/Fragment.java
@@ -1371,7 +1371,7 @@
* @param savedInstanceState If non-null, this fragment is being re-constructed
* from a previous saved state as given here.
*/
- public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
}
/**
@@ -1469,7 +1469,7 @@
*
* @param outState Bundle in which to place your saved state.
*/
- public void onSaveInstanceState(Bundle outState) {
+ public void onSaveInstanceState(@NonNull Bundle outState) {
}
/**
diff --git a/fragment/java/android/support/v4/app/FragmentActivity.java b/fragment/java/android/support/v4/app/FragmentActivity.java
index e513ff7..d6e446c 100644
--- a/fragment/java/android/support/v4/app/FragmentActivity.java
+++ b/fragment/java/android/support/v4/app/FragmentActivity.java
@@ -760,6 +760,7 @@
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
+ mFragments.noteStateNotSaved();
int index = (requestCode >> 16) & 0xffff;
if (index != 0) {
index--;
diff --git a/fragment/java/android/support/v4/app/ListFragment.java b/fragment/java/android/support/v4/app/ListFragment.java
index 21617ad..496bd8e 100644
--- a/fragment/java/android/support/v4/app/ListFragment.java
+++ b/fragment/java/android/support/v4/app/ListFragment.java
@@ -19,6 +19,8 @@
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
@@ -142,7 +144,7 @@
* Attach to list view once the view hierarchy has been created.
*/
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ensureList();
}
diff --git a/lifecycle/extensions/build.gradle b/lifecycle/extensions/build.gradle
index 241e99a..9d33e55 100644
--- a/lifecycle/extensions/build.gradle
+++ b/lifecycle/extensions/build.gradle
@@ -39,11 +39,11 @@
}
}
dependencies {
- compile project(":lifecycle:common")
compile project(":lifecycle:runtime")
compile project(":arch:common")
compile project(":arch:runtime")
compile libs.support.fragments, libs.support_exclude_config
+ compile project(":lifecycle:common")
annotationProcessor project(":lifecycle:compiler")
diff --git a/lifecycle/extensions/src/main/java/android/arch/lifecycle/ComputableLiveData.java b/lifecycle/extensions/src/main/java/android/arch/lifecycle/ComputableLiveData.java
index fe18243..1ddcb1a 100644
--- a/lifecycle/extensions/src/main/java/android/arch/lifecycle/ComputableLiveData.java
+++ b/lifecycle/extensions/src/main/java/android/arch/lifecycle/ComputableLiveData.java
@@ -16,7 +16,7 @@
package android.arch.lifecycle;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.RestrictTo;
@@ -53,7 +53,7 @@
@Override
protected void onActive() {
// TODO if we make this class public, we should accept an executor
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
}
};
}
@@ -115,7 +115,7 @@
if (mInvalid.compareAndSet(false, true)) {
if (isActive) {
// TODO if we make this class public, we should accept an executor.
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
}
}
}
@@ -127,7 +127,7 @@
* When there are active observers, this will trigger a call to {@link #compute()}.
*/
public void invalidate() {
- AppToolkitTaskExecutor.getInstance().executeOnMainThread(mInvalidationRunnable);
+ ArchTaskExecutor.getInstance().executeOnMainThread(mInvalidationRunnable);
}
@SuppressWarnings("WeakerAccess")
diff --git a/lifecycle/extensions/src/main/java/android/arch/lifecycle/LiveData.java b/lifecycle/extensions/src/main/java/android/arch/lifecycle/LiveData.java
index 99d859c..da5600c 100644
--- a/lifecycle/extensions/src/main/java/android/arch/lifecycle/LiveData.java
+++ b/lifecycle/extensions/src/main/java/android/arch/lifecycle/LiveData.java
@@ -19,7 +19,7 @@
import static android.arch.lifecycle.Lifecycle.State.DESTROYED;
import static android.arch.lifecycle.Lifecycle.State.STARTED;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.internal.SafeIterableMap;
import android.arch.lifecycle.Lifecycle.State;
import android.support.annotation.MainThread;
@@ -197,7 +197,6 @@
return;
}
owner.getLifecycle().addObserver(wrapper);
- wrapper.activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
}
/**
@@ -274,7 +273,7 @@
if (!postTask) {
return;
}
- AppToolkitTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
+ ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
/**
@@ -376,7 +375,6 @@
// immediately set active state, so we'd never dispatch anything to inactive
// owner
activeStateChanged(isActiveState(owner.getLifecycle().getCurrentState()));
-
}
void activeStateChanged(boolean newActive) {
@@ -403,7 +401,7 @@
}
private void assertMainThread(String methodName) {
- if (!AppToolkitTaskExecutor.getInstance().isMainThread()) {
+ if (!ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot invoke " + methodName + " on a background"
+ " thread");
}
diff --git a/lifecycle/extensions/src/test/java/android/arch/lifecycle/ComputableLiveDataTest.java b/lifecycle/extensions/src/test/java/android/arch/lifecycle/ComputableLiveDataTest.java
index 0a3fbed..eb89d8d 100644
--- a/lifecycle/extensions/src/test/java/android/arch/lifecycle/ComputableLiveDataTest.java
+++ b/lifecycle/extensions/src/test/java/android/arch/lifecycle/ComputableLiveDataTest.java
@@ -27,7 +27,7 @@
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.verify;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.TaskExecutor;
import android.arch.core.executor.TaskExecutorWithFakeMainThread;
import android.arch.lifecycle.util.InstantTaskExecutor;
@@ -58,12 +58,12 @@
@Before
public void swapExecutorDelegate() {
mTaskExecutor = spy(new InstantTaskExecutor());
- AppToolkitTaskExecutor.getInstance().setDelegate(mTaskExecutor);
+ ArchTaskExecutor.getInstance().setDelegate(mTaskExecutor);
}
@After
public void removeExecutorDelegate() {
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
@Test
@@ -76,7 +76,7 @@
@Test
public void noConcurrentCompute() throws InterruptedException {
TaskExecutorWithFakeMainThread executor = new TaskExecutorWithFakeMainThread(2);
- AppToolkitTaskExecutor.getInstance().setDelegate(executor);
+ ArchTaskExecutor.getInstance().setDelegate(executor);
try {
// # of compute calls
final Semaphore computeCounter = new Semaphore(0);
@@ -121,7 +121,7 @@
// assert no other results arrive
verify(observer, never()).onChanged(anyInt());
} finally {
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
}
diff --git a/lifecycle/extensions/src/test/java/android/arch/lifecycle/LiveDataTest.java b/lifecycle/extensions/src/test/java/android/arch/lifecycle/LiveDataTest.java
index ed2a35d..9f0b425 100644
--- a/lifecycle/extensions/src/test/java/android/arch/lifecycle/LiveDataTest.java
+++ b/lifecycle/extensions/src/test/java/android/arch/lifecycle/LiveDataTest.java
@@ -36,16 +36,20 @@
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.lifecycle.util.InstantTaskExecutor;
import android.support.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.InOrder;
import org.mockito.Mockito;
@SuppressWarnings({"unchecked"})
+@RunWith(JUnit4.class)
public class LiveDataTest {
private PublicLiveData<String> mLiveData;
private LifecycleOwner mOwner;
@@ -66,12 +70,12 @@
@Before
public void swapExecutorDelegate() {
- AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+ ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
}
@After
public void removeExecutorDelegate() {
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
@Test
@@ -418,6 +422,40 @@
verify(mActiveObserversChanged, never()).onCall(anyBoolean());
}
+ @Test
+ public void testRemoveDuringAddition() {
+ mRegistry.handleLifecycleEvent(ON_START);
+ mLiveData.setValue("bla");
+ mLiveData.observeForever(new Observer<String>() {
+ @Override
+ public void onChanged(@Nullable String s) {
+ mLiveData.removeObserver(this);
+ }
+ });
+ assertThat(mLiveData.hasActiveObservers(), is(false));
+ InOrder inOrder = Mockito.inOrder(mActiveObserversChanged);
+ inOrder.verify(mActiveObserversChanged).onCall(true);
+ inOrder.verify(mActiveObserversChanged).onCall(false);
+ inOrder.verifyNoMoreInteractions();
+ }
+
+ @Test
+ public void testRemoveDuringBringingUpToState() {
+ mLiveData.setValue("bla");
+ mLiveData.observeForever(new Observer<String>() {
+ @Override
+ public void onChanged(@Nullable String s) {
+ mLiveData.removeObserver(this);
+ }
+ });
+ mRegistry.handleLifecycleEvent(ON_RESUME);
+ assertThat(mLiveData.hasActiveObservers(), is(false));
+ InOrder inOrder = Mockito.inOrder(mActiveObserversChanged);
+ inOrder.verify(mActiveObserversChanged).onCall(true);
+ inOrder.verify(mActiveObserversChanged).onCall(false);
+ inOrder.verifyNoMoreInteractions();
+ }
+
@SuppressWarnings("WeakerAccess")
static class PublicLiveData<T> extends LiveData<T> {
// cannot spy due to internal calls
diff --git a/lifecycle/extensions/src/test/java/android/arch/lifecycle/MediatorLiveDataTest.java b/lifecycle/extensions/src/test/java/android/arch/lifecycle/MediatorLiveDataTest.java
index 3de3eee..e2eadbe 100644
--- a/lifecycle/extensions/src/test/java/android/arch/lifecycle/MediatorLiveDataTest.java
+++ b/lifecycle/extensions/src/test/java/android/arch/lifecycle/MediatorLiveDataTest.java
@@ -25,7 +25,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.lifecycle.util.InstantTaskExecutor;
import android.support.annotation.Nullable;
@@ -69,7 +69,7 @@
@Before
public void swapExecutorDelegate() {
- AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+ ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
}
@Test
diff --git a/lifecycle/extensions/src/test/java/android/arch/lifecycle/TransformationsTest.java b/lifecycle/extensions/src/test/java/android/arch/lifecycle/TransformationsTest.java
index e92ecca..940a3e8 100644
--- a/lifecycle/extensions/src/test/java/android/arch/lifecycle/TransformationsTest.java
+++ b/lifecycle/extensions/src/test/java/android/arch/lifecycle/TransformationsTest.java
@@ -25,7 +25,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.util.Function;
import android.arch.lifecycle.util.InstantTaskExecutor;
@@ -42,7 +42,7 @@
@Before
public void swapExecutorDelegate() {
- AppToolkitTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
+ ArchTaskExecutor.getInstance().setDelegate(new InstantTaskExecutor());
}
@Before
diff --git a/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java b/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
index 0be0149..ec9b7f1 100644
--- a/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
+++ b/lifecycle/reactivestreams/src/main/java/android/arch/lifecycle/LiveDataReactiveStreams.java
@@ -16,7 +16,7 @@
package android.arch.lifecycle;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.support.annotation.Nullable;
import org.reactivestreams.Publisher;
@@ -85,7 +85,7 @@
if (n < 0 || mCanceled) {
return;
}
- AppToolkitTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
+ ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
@Override
public void run() {
if (mCanceled) {
@@ -110,7 +110,7 @@
if (mCanceled) {
return;
}
- AppToolkitTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
+ ArchTaskExecutor.getInstance().executeOnMainThread(new Runnable() {
@Override
public void run() {
if (mCanceled) {
diff --git a/lifecycle/reactivestreams/src/test/java/android/arch/lifecycle/LiveDataReactiveStreamsTest.java b/lifecycle/reactivestreams/src/test/java/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
index 87fba27..ca52ee5 100644
--- a/lifecycle/reactivestreams/src/test/java/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
+++ b/lifecycle/reactivestreams/src/test/java/android/arch/lifecycle/LiveDataReactiveStreamsTest.java
@@ -16,12 +16,10 @@
package android.arch.lifecycle;
-import static android.arch.lifecycle.Lifecycle.State.RESUMED;
-
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.TaskExecutor;
import android.support.annotation.Nullable;
import android.support.test.filters.SmallTest;
@@ -47,28 +45,7 @@
@SmallTest
public class LiveDataReactiveStreamsTest {
- private static final Lifecycle sLifecycle = new Lifecycle() {
- @Override
- public void addObserver(LifecycleObserver observer) {
- }
-
- @Override
- public void removeObserver(LifecycleObserver observer) {
- }
-
- @Override
- public State getCurrentState() {
- return RESUMED;
- }
- };
- private static final LifecycleOwner S_LIFECYCLE_OWNER = new LifecycleOwner() {
-
- @Override
- public Lifecycle getLifecycle() {
- return sLifecycle;
- }
-
- };
+ private LifecycleOwner mLifecycleOwner;
private final List<String> mLiveDataOutput = new ArrayList<>();
private final Observer<String> mObserver = new Observer<String>() {
@@ -85,8 +62,19 @@
@Before
public void init() {
+ mLifecycleOwner = new LifecycleOwner() {
+ LifecycleRegistry mRegistry = new LifecycleRegistry(this);
+ {
+ mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
+ }
+
+ @Override
+ public Lifecycle getLifecycle() {
+ return mRegistry;
+ }
+ };
mTestThread = Thread.currentThread();
- AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+ ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
@Override
public void executeOnDiskIO(Runnable runnable) {
@@ -109,7 +97,7 @@
@After
public void removeExecutorDelegate() {
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
@Test
@@ -117,7 +105,7 @@
PublishProcessor<String> processor = PublishProcessor.create();
LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(processor);
- liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+ liveData.observe(mLifecycleOwner, mObserver);
processor.onNext("foo");
processor.onNext("bar");
@@ -132,13 +120,13 @@
PublishProcessor<String> processor = PublishProcessor.create();
LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(processor);
- liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+ liveData.observe(mLifecycleOwner, mObserver);
processor.onNext("foo");
processor.onNext("bar");
// The second mObserver should only get the newest value and any later values.
- liveData.observe(S_LIFECYCLE_OWNER, new Observer<String>() {
+ liveData.observe(mLifecycleOwner, new Observer<String>() {
@Override
public void onChanged(@Nullable String s) {
output2.add(s);
@@ -157,7 +145,7 @@
.concatWith(Flowable.just("bar", "baz").observeOn(sBackgroundScheduler));
LiveData<String> liveData = LiveDataReactiveStreams.fromPublisher(input);
- liveData.observe(S_LIFECYCLE_OWNER, mObserver);
+ liveData.observe(mLifecycleOwner, mObserver);
assertThat(mLiveDataOutput, is(Collections.singletonList("foo")));
sBackgroundScheduler.triggerActions();
@@ -170,7 +158,7 @@
liveData.setValue("foo");
assertThat(liveData.getValue(), is("foo"));
- Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+ Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
.subscribe(mOutputProcessor);
liveData.setValue("bar");
@@ -188,7 +176,7 @@
assertThat(liveData.getValue(), is("foo"));
Disposable disposable = Flowable
- .fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+ .fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
@@ -216,7 +204,7 @@
final AsyncSubject<Subscription> subscriptionSubject = AsyncSubject.create();
- Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+ Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
.subscribe(new Subscriber<String>() {
@Override
public void onSubscribe(Subscription s) {
@@ -275,7 +263,7 @@
public void convertsToPublisherWithAsyncData() {
MutableLiveData<String> liveData = new MutableLiveData<>();
- Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(S_LIFECYCLE_OWNER, liveData))
+ Flowable.fromPublisher(LiveDataReactiveStreams.toPublisher(mLifecycleOwner, liveData))
.observeOn(sBackgroundScheduler)
.subscribe(mOutputProcessor);
diff --git a/paging/runtime/src/main/java/android/arch/paging/LivePagedListProvider.java b/paging/runtime/src/main/java/android/arch/paging/LivePagedListProvider.java
index 1250aa1..07dd84b 100644
--- a/paging/runtime/src/main/java/android/arch/paging/LivePagedListProvider.java
+++ b/paging/runtime/src/main/java/android/arch/paging/LivePagedListProvider.java
@@ -16,7 +16,7 @@
package android.arch.paging;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.lifecycle.ComputableLiveData;
import android.arch.lifecycle.LiveData;
import android.support.annotation.AnyThread;
@@ -134,9 +134,9 @@
mList = new PagedList.Builder<Key, Value>()
.setDataSource(mDataSource)
- .setMainThreadExecutor(AppToolkitTaskExecutor.getMainThreadExecutor())
+ .setMainThreadExecutor(ArchTaskExecutor.getMainThreadExecutor())
.setBackgroundThreadExecutor(
- AppToolkitTaskExecutor.getIOThreadExecutor())
+ ArchTaskExecutor.getIOThreadExecutor())
.setConfig(config)
.setInitialKey(initializeKey)
.build();
diff --git a/paging/runtime/src/main/java/android/support/v7/recyclerview/extensions/ListAdapterConfig.java b/paging/runtime/src/main/java/android/support/v7/recyclerview/extensions/ListAdapterConfig.java
index f861242..25697a1 100644
--- a/paging/runtime/src/main/java/android/support/v7/recyclerview/extensions/ListAdapterConfig.java
+++ b/paging/runtime/src/main/java/android/support/v7/recyclerview/extensions/ListAdapterConfig.java
@@ -16,7 +16,7 @@
package android.support.v7.recyclerview.extensions;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import java.util.concurrent.Executor;
@@ -118,10 +118,10 @@
throw new IllegalArgumentException("Must provide a diffCallback");
}
if (mBackgroundThreadExecutor == null) {
- mBackgroundThreadExecutor = AppToolkitTaskExecutor.getIOThreadExecutor();
+ mBackgroundThreadExecutor = ArchTaskExecutor.getIOThreadExecutor();
}
if (mMainThreadExecutor == null) {
- mMainThreadExecutor = AppToolkitTaskExecutor.getMainThreadExecutor();
+ mMainThreadExecutor = ArchTaskExecutor.getMainThreadExecutor();
}
return new ListAdapterConfig<>(
mMainThreadExecutor,
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
index 6dc71f6..daaa8e3 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/ext/javapoet_ext.kt
@@ -84,7 +84,7 @@
object ArchTypeNames {
val APP_EXECUTOR : ClassName =
- ClassName.get("android.arch.core.executor", "AppToolkitTaskExecutor")
+ ClassName.get("android.arch.core.executor", "ArchTaskExecutor")
}
object PagingTypeNames {
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
index a4e8946..85e89d1 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/parser/SqlParser.kt
@@ -24,7 +24,6 @@
import org.antlr.v4.runtime.Recognizer
import org.antlr.v4.runtime.tree.ParseTree
import org.antlr.v4.runtime.tree.TerminalNode
-import java.util.ArrayList
import javax.annotation.processing.ProcessingEnvironment
import javax.lang.model.type.TypeKind
import javax.lang.model.type.TypeMirror
@@ -120,6 +119,7 @@
class SqlParser {
companion object {
+ private val INVALID_IDENTIFIER_CHARS = arrayOf('`', '\"')
fun parse(input: String): ParsedQuery {
val inputStream = ANTLRInputStream(input)
val lexer = SQLiteLexer(inputStream)
@@ -153,6 +153,9 @@
listOf("unknown error while parsing $input : ${antlrError.message}"))
}
}
+
+ fun isValidIdentifier(input : String) : Boolean =
+ input.isNotBlank() && INVALID_IDENTIFIER_CHARS.none { input.contains(it) }
}
}
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
index cb8dd13..540c95a 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/EntityProcessor.kt
@@ -22,6 +22,7 @@
import android.arch.persistence.room.ext.getAsStringList
import android.arch.persistence.room.ext.toType
import android.arch.persistence.room.parser.SQLTypeAffinity
+import android.arch.persistence.room.parser.SqlParser
import android.arch.persistence.room.processor.ProcessorErrors.INDEX_COLUMNS_CANNOT_BE_EMPTY
import android.arch.persistence.room.processor.ProcessorErrors.RELATION_IN_ENTITY
import android.arch.persistence.room.processor.cache.Cache
@@ -127,6 +128,13 @@
val entityForeignKeys = validateAndCreateForeignKeyReferences(foreignKeyInputs, pojo)
checkIndicesForForeignKeys(entityForeignKeys, primaryKey, indices)
+ context.checker.check(SqlParser.isValidIdentifier(tableName), element,
+ ProcessorErrors.INVALID_TABLE_NAME)
+ pojo.fields.forEach {
+ context.checker.check(SqlParser.isValidIdentifier(it.columnName), it.element,
+ ProcessorErrors.INVALID_COLUMN_NAME)
+ }
+
val entity = Entity(element = element,
tableName = tableName,
type = pojo.type,
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
index b1e8661..8058ff9 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/processor/ProcessorErrors.kt
@@ -17,7 +17,6 @@
package android.arch.persistence.room.processor
import android.arch.persistence.room.Delete
-import android.arch.persistence.room.Embedded
import android.arch.persistence.room.Insert
import android.arch.persistence.room.Query
import android.arch.persistence.room.Update
@@ -200,6 +199,16 @@
""".trim()
}
+ fun pojoMissingNonNull(pojoTypeName: TypeName, missingPojoFields: List<String>,
+ allQueryColumns: List<String>) : String {
+ return """
+ The columns returned by the query does not have the fields
+ [${missingPojoFields.joinToString(",")}] in $pojoTypeName even though they are
+ annotated as non-null or primitive.
+ Columns returned by the query: [${allQueryColumns.joinToString(",")}]
+ """.trim()
+ }
+
fun cursorPojoMismatch(pojoTypeName: TypeName,
unusedColumns: List<String>, allColumns: List<String>,
unusedFields: List<Field>, allFields: List<Field>): String {
@@ -459,4 +468,9 @@
"bug and Room does not allow it. See SQLite docs for details: " +
"https://www.sqlite.org/lang_createtable.html"
}
+
+ val INVALID_COLUMN_NAME = "Invalid column name. Room does not allow using ` or \" in column" +
+ " names"
+
+ val INVALID_TABLE_NAME = "Invalid table name. Room does not allow using ` or \" in table names"
}
diff --git a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
index 062b179..a013dc7 100644
--- a/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
+++ b/room/compiler/src/main/kotlin/android/arch/persistence/room/solver/query/result/PojoRowAdapter.kt
@@ -19,7 +19,6 @@
import android.arch.persistence.room.ext.L
import android.arch.persistence.room.ext.S
import android.arch.persistence.room.ext.T
-import android.arch.persistence.room.ext.typeName
import android.arch.persistence.room.processor.Context
import android.arch.persistence.room.processor.ProcessorErrors
import android.arch.persistence.room.solver.CodeGenScope
@@ -71,6 +70,13 @@
)
context.logger.w(Warning.CURSOR_MISMATCH, null, warningMsg)
}
+ val nonNulls = remainingFields.filter { it.nonNull }
+ if (nonNulls.isNotEmpty()) {
+ context.logger.e(ProcessorErrors.pojoMissingNonNull(
+ pojoTypeName = pojo.typeName,
+ missingPojoFields = nonNulls.map { it.name },
+ allQueryColumns = info.columns.map { it.name }))
+ }
if (matchedFields.isEmpty()) {
context.logger.e(ProcessorErrors.CANNOT_FIND_QUERY_RESULT_ADAPTER)
}
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
index 68b1868..6d3e194 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/parser/SqlParserTest.kt
@@ -63,6 +63,22 @@
}
@Test
+ fun validColumnNames() {
+ listOf("f", "fo", "f2", "f 2", "foo_2", "foo-2", "_", "foo bar baz",
+ "foo 2 baz", "_baz", "fooBar", "2", "*", "foo*2", "dsa$", "\$fsa",
+ "-bar", "ÅŸoöÄŸüı").forEach {
+ assertThat("name: $it", SqlParser.isValidIdentifier(it), `is`(true))
+ }
+ }
+
+ @Test
+ fun invalidColumnNames() {
+ listOf("", " ", "fd`a`", "f`a", "`a", "\"foo bar\"", "\"", "`").forEach {
+ assertThat("name: $it", SqlParser.isValidIdentifier(it), `is`(false))
+ }
+ }
+
+ @Test
fun extractTableNames() {
assertThat(SqlParser.parse("select * from users").tables,
`is`(setOf(Table("users", "users"))))
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
index 42fc3df..533d8c4 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/EntityProcessorTest.kt
@@ -1775,7 +1775,47 @@
@Embedded
MyEntity myEntity;
}
- """){ _, _ ->
+ """) { _, _ ->
}.failsToCompile().withErrorContaining(ProcessorErrors.RECURSIVE_REFERENCE_DETECTED.format("foo.bar.MyEntity -> foo.bar.MyEntity.A -> foo.bar.MyEntity"))
}
+ fun okTableName() {
+ val annotation = mapOf("tableName" to "\"foo bar\"")
+ singleEntity(
+ """
+ @PrimaryKey
+ int id;
+ String name;
+ """,
+ attributes = annotation, jfos = listOf(COMMON.USER)
+ ){ _, _ ->
+ }.compilesWithoutError()
+ }
+
+ @Test
+ fun badTableName() {
+ val annotation = mapOf("tableName" to """ "foo`bar" """)
+ singleEntity(
+ """
+ @PrimaryKey
+ int id;
+ String name;
+ """,
+ attributes = annotation, jfos = listOf(COMMON.USER)
+ ){ _, _ ->
+ }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_TABLE_NAME)
+ }
+
+ @Test
+ fun badColumnName() {
+ singleEntity(
+ """
+ @PrimaryKey
+ int id;
+ @ColumnInfo(name = "\"foo bar\"")
+ String name;
+ """,
+ jfos = listOf(COMMON.USER)
+ ){ _, _ ->
+ }.failsToCompile().withErrorContaining(ProcessorErrors.INVALID_COLUMN_NAME)
+ }
}
diff --git a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
index 7e892b7..a2cb768 100644
--- a/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
+++ b/room/compiler/src/test/kotlin/android/arch/persistence/room/processor/QueryMethodProcessorTest.kt
@@ -70,6 +70,7 @@
companion object {
const val DAO_PREFIX = """
package foo.bar;
+ import android.support.annotation.NonNull;
import android.arch.persistence.room.*;
@Dao
abstract class MyClass {
@@ -599,6 +600,30 @@
}
@Test
+ fun pojo_missingNonNull() {
+ pojoTest("""
+ @NonNull
+ String name;
+ String lastName;
+ """, listOf("lastName")) { adapter, _, _ ->
+ assertThat(adapter?.mapping?.unusedColumns, `is`(emptyList()))
+ assertThat(adapter?.mapping?.unusedFields, `is`(
+ adapter?.pojo?.fields?.filter { it.name == "name" }
+ ))
+ }?.failsToCompile()?.withWarningContaining(
+ ProcessorErrors.cursorPojoMismatch(
+ pojoTypeName = POJO,
+ unusedColumns = emptyList(),
+ unusedFields = listOf(createField("name")),
+ allColumns = listOf("lastName"),
+ allFields = listOf(createField("name"), createField("lastName"))
+ ))?.and()?.withErrorContaining(
+ ProcessorErrors.pojoMissingNonNull(pojoTypeName = POJO,
+ missingPojoFields = listOf("name"),
+ allQueryColumns = listOf("lastName")))
+ }
+
+ @Test
fun pojo_tooManyFieldsAndColumns() {
pojoTest("""
String name;
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/TestDatabase.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/TestDatabase.java
index 9417296..2fad7b1 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/TestDatabase.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/TestDatabase.java
@@ -21,6 +21,7 @@
import android.arch.persistence.room.TypeConverter;
import android.arch.persistence.room.TypeConverters;
import android.arch.persistence.room.integration.testapp.dao.BlobEntityDao;
+import android.arch.persistence.room.integration.testapp.dao.FunnyNamedDao;
import android.arch.persistence.room.integration.testapp.dao.PetCoupleDao;
import android.arch.persistence.room.integration.testapp.dao.PetDao;
import android.arch.persistence.room.integration.testapp.dao.ProductDao;
@@ -31,6 +32,7 @@
import android.arch.persistence.room.integration.testapp.dao.UserPetDao;
import android.arch.persistence.room.integration.testapp.dao.WithClauseDao;
import android.arch.persistence.room.integration.testapp.vo.BlobEntity;
+import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity;
import android.arch.persistence.room.integration.testapp.vo.Pet;
import android.arch.persistence.room.integration.testapp.vo.PetCouple;
import android.arch.persistence.room.integration.testapp.vo.Product;
@@ -41,7 +43,7 @@
import java.util.Date;
@Database(entities = {User.class, Pet.class, School.class, PetCouple.class, Toy.class,
- BlobEntity.class, Product.class},
+ BlobEntity.class, Product.class, FunnyNamedEntity.class},
version = 1, exportSchema = false)
@TypeConverters(TestDatabase.Converters.class)
public abstract class TestDatabase extends RoomDatabase {
@@ -55,6 +57,7 @@
public abstract ProductDao getProductDao();
public abstract SpecificDogDao getSpecificDogDao();
public abstract WithClauseDao getWithClauseDao();
+ public abstract FunnyNamedDao getFunnyNamedDao();
@SuppressWarnings("unused")
public static class Converters {
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java
new file mode 100644
index 0000000..93b5e72
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/FunnyNamedDao.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.arch.persistence.room.integration.testapp.dao;
+
+import static android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity.COLUMN_ID;
+import static android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity.TABLE_NAME;
+
+import android.arch.lifecycle.LiveData;
+import android.arch.persistence.room.Dao;
+import android.arch.persistence.room.Delete;
+import android.arch.persistence.room.Insert;
+import android.arch.persistence.room.Query;
+import android.arch.persistence.room.Update;
+import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity;
+
+import java.util.List;
+
+@Dao
+public interface FunnyNamedDao {
+ String SELECT_ONE = "select * from \"" + TABLE_NAME + "\" WHERE \"" + COLUMN_ID + "\" = :id";
+ @Insert
+ void insert(FunnyNamedEntity... entities);
+ @Delete
+ void delete(FunnyNamedEntity... entities);
+ @Update
+ void update(FunnyNamedEntity... entities);
+
+ @Query("select * from \"" + TABLE_NAME + "\" WHERE \"" + COLUMN_ID + "\" IN (:ids)")
+ List<FunnyNamedEntity> loadAll(int... ids);
+
+ @Query(SELECT_ONE)
+ LiveData<FunnyNamedEntity> observableOne(int id);
+
+ @Query(SELECT_ONE)
+ FunnyNamedEntity load(int id);
+}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
index 7bb137f..18e8d93 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/dao/SchoolDao.java
@@ -35,16 +35,16 @@
@Query("SELECT * from School WHERE address_street LIKE '%' || :street || '%'")
public abstract List<School> findByStreet(String street);
- @Query("SELECT mName, manager_mName FROM School")
+ @Query("SELECT mId, mName, manager_mName FROM School")
public abstract List<School> schoolAndManagerNames();
- @Query("SELECT mName, manager_mName FROM School")
+ @Query("SELECT mId, mName, manager_mName FROM School")
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
public abstract List<SchoolRef> schoolAndManagerNamesAsPojo();
@Query("SELECT address_lat as lat, address_lng as lng FROM School WHERE mId = :schoolId")
public abstract Coordinates loadCoordinates(int schoolId);
- @Query("SELECT address_lat, address_lng FROM School WHERE mId = :schoolId")
+ @Query("SELECT mId, address_lat, address_lng FROM School WHERE mId = :schoolId")
public abstract School loadCoordinatesAsSchool(int schoolId);
}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java
index 4c9d73e..df70a17 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/paging/LivePagedListProviderTest.java
@@ -21,17 +21,17 @@
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.testing.CountingTaskExecutorRule;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleOwner;
import android.arch.lifecycle.LifecycleRegistry;
import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.Observer;
+import android.arch.paging.PagedList;
import android.arch.persistence.room.integration.testapp.test.TestDatabaseTest;
import android.arch.persistence.room.integration.testapp.test.TestUtil;
import android.arch.persistence.room.integration.testapp.vo.User;
-import android.arch.paging.PagedList;
import android.support.annotation.Nullable;
import android.support.test.filters.LargeTest;
import android.support.test.runner.AndroidJUnit4;
@@ -131,7 +131,7 @@
return null;
}
});
- AppToolkitTaskExecutor.getInstance().executeOnMainThread(futureTask);
+ ArchTaskExecutor.getInstance().executeOnMainThread(futureTask);
futureTask.get();
}
@@ -155,7 +155,7 @@
private static class PagedListObserver<T> implements Observer<PagedList<T>> {
private PagedList<T> mList;
- public void reset() {
+ void reset() {
mList = null;
}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java
new file mode 100644
index 0000000..f4fca7f
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/FunnyNamedDaoTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.arch.persistence.room.integration.testapp.test;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import android.arch.core.executor.testing.CountingTaskExecutorRule;
+import android.arch.lifecycle.Observer;
+import android.arch.persistence.room.integration.testapp.vo.FunnyNamedEntity;
+import android.support.annotation.Nullable;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class FunnyNamedDaoTest extends TestDatabaseTest {
+ @Rule
+ public CountingTaskExecutorRule mExecutorRule = new CountingTaskExecutorRule();
+
+ @Test
+ public void readWrite() {
+ FunnyNamedEntity entity = new FunnyNamedEntity(1, "a");
+ mFunnyNamedDao.insert(entity);
+ FunnyNamedEntity loaded = mFunnyNamedDao.load(1);
+ assertThat(loaded, is(entity));
+ }
+
+ @Test
+ public void update() {
+ FunnyNamedEntity entity = new FunnyNamedEntity(1, "a");
+ mFunnyNamedDao.insert(entity);
+ entity.setValue("b");
+ mFunnyNamedDao.update(entity);
+ FunnyNamedEntity loaded = mFunnyNamedDao.load(1);
+ assertThat(loaded.getValue(), is("b"));
+ }
+
+ @Test
+ public void delete() {
+ FunnyNamedEntity entity = new FunnyNamedEntity(1, "a");
+ mFunnyNamedDao.insert(entity);
+ assertThat(mFunnyNamedDao.load(1), notNullValue());
+ mFunnyNamedDao.delete(entity);
+ assertThat(mFunnyNamedDao.load(1), nullValue());
+ }
+
+ @Test
+ public void observe() throws TimeoutException, InterruptedException {
+ final FunnyNamedEntity[] item = new FunnyNamedEntity[1];
+ mFunnyNamedDao.observableOne(2).observeForever(new Observer<FunnyNamedEntity>() {
+ @Override
+ public void onChanged(@Nullable FunnyNamedEntity funnyNamedEntity) {
+ item[0] = funnyNamedEntity;
+ }
+ });
+
+ FunnyNamedEntity entity = new FunnyNamedEntity(1, "a");
+ mFunnyNamedDao.insert(entity);
+ mExecutorRule.drainTasks(1, TimeUnit.MINUTES);
+ assertThat(item[0], nullValue());
+
+ final FunnyNamedEntity entity2 = new FunnyNamedEntity(2, "b");
+ mFunnyNamedDao.insert(entity2);
+ mExecutorRule.drainTasks(1, TimeUnit.MINUTES);
+ assertThat(item[0], is(entity2));
+
+ final FunnyNamedEntity entity3 = new FunnyNamedEntity(2, "c");
+ mFunnyNamedDao.update(entity3);
+ mExecutorRule.drainTasks(1, TimeUnit.MINUTES);
+ assertThat(item[0], is(entity3));
+ }
+}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java
index 4787ce5..84f20ec 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/InvalidationTest.java
@@ -21,7 +21,7 @@
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.TaskExecutor;
import android.arch.persistence.room.InvalidationTracker;
import android.arch.persistence.room.Room;
@@ -68,7 +68,7 @@
@Before
public void setSingleThreadedIO() {
- AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+ ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
ExecutorService mIOExecutor = Executors.newSingleThreadExecutor();
Handler mHandler = new Handler(Looper.getMainLooper());
@@ -91,7 +91,7 @@
@After
public void clearExecutor() {
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
private void waitUntilIOThreadIsIdle() {
@@ -101,7 +101,7 @@
return null;
}
});
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(future);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(future);
//noinspection TryWithIdenticalCatches
try {
future.get();
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java
index cae8445..b1f6851 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/LiveDataQueryTest.java
@@ -21,7 +21,7 @@
import static org.hamcrest.CoreMatchers.nullValue;
import static org.hamcrest.MatcherAssert.assertThat;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.testing.CountingTaskExecutorRule;
import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleOwner;
@@ -322,7 +322,7 @@
return null;
}
});
- AppToolkitTaskExecutor.getInstance().executeOnMainThread(futureTask);
+ ArchTaskExecutor.getInstance().executeOnMainThread(futureTask);
futureTask.get();
}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java
index 98783f2..01d071e 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2Test.java
@@ -19,7 +19,7 @@
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.executor.TaskExecutor;
import android.arch.persistence.room.EmptyResultSetException;
import android.arch.persistence.room.integration.testapp.vo.Pet;
@@ -55,7 +55,7 @@
public void setupSchedulers() {
mTestScheduler = new TestScheduler();
mTestScheduler.start();
- AppToolkitTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
+ ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
@Override
public void executeOnDiskIO(Runnable runnable) {
mTestScheduler.scheduleDirect(runnable);
@@ -76,7 +76,7 @@
@After
public void clearSchedulers() {
mTestScheduler.shutdown();
- AppToolkitTaskExecutor.getInstance().setDelegate(null);
+ ArchTaskExecutor.getInstance().setDelegate(null);
}
private void drain() throws InterruptedException {
@@ -305,4 +305,27 @@
}
});
}
+
+ @Test
+ public void flowable_updateInTransaction() throws InterruptedException {
+ // When subscribing to the emissions of the user
+ final TestSubscriber<User> userTestSubscriber = mUserDao
+ .flowableUserById(3)
+ .observeOn(mTestScheduler)
+ .test();
+ drain();
+ userTestSubscriber.assertValueCount(0);
+
+ // When inserting a new user in the data source
+ mDatabase.beginTransaction();
+ try {
+ mUserDao.insert(TestUtil.createUser(3));
+ mDatabase.setTransactionSuccessful();
+
+ } finally {
+ mDatabase.endTransaction();
+ }
+ drain();
+ userTestSubscriber.assertValueCount(1);
+ }
}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
new file mode 100644
index 0000000..fcd0b00
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/RxJava2WithInstantTaskExecutorTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.arch.persistence.room.integration.testapp.test;
+
+import android.arch.core.executor.testing.InstantTaskExecutorRule;
+import android.arch.persistence.room.Room;
+import android.arch.persistence.room.integration.testapp.TestDatabase;
+import android.arch.persistence.room.integration.testapp.vo.User;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import io.reactivex.subscribers.TestSubscriber;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class RxJava2WithInstantTaskExecutorTest {
+ @Rule
+ public InstantTaskExecutorRule instantTaskExecutorRule = new InstantTaskExecutorRule();
+
+ private TestDatabase mDatabase;
+
+ @Before
+ public void initDb() throws Exception {
+ // using an in-memory database because the information stored here disappears when the
+ // process is killed
+ mDatabase = Room.inMemoryDatabaseBuilder(InstrumentationRegistry.getContext(),
+ TestDatabase.class)
+ // allowing main thread queries, just for testing
+ .allowMainThreadQueries()
+ .build();
+ }
+
+ @Test
+ public void testFlowableInTransaction() {
+ // When subscribing to the emissions of the user
+ TestSubscriber<User> subscriber = mDatabase.getUserDao().flowableUserById(3).test();
+ subscriber.assertValueCount(0);
+
+ // When inserting a new user in the data source
+ mDatabase.beginTransaction();
+ try {
+ mDatabase.getUserDao().insert(TestUtil.createUser(3));
+ mDatabase.setTransactionSuccessful();
+ } finally {
+ mDatabase.endTransaction();
+ }
+
+ subscriber.assertValueCount(1);
+ }
+}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java
index 51d5bb3..ec77561 100644
--- a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/test/TestDatabaseTest.java
@@ -18,6 +18,7 @@
import android.arch.persistence.room.Room;
import android.arch.persistence.room.integration.testapp.TestDatabase;
+import android.arch.persistence.room.integration.testapp.dao.FunnyNamedDao;
import android.arch.persistence.room.integration.testapp.dao.PetCoupleDao;
import android.arch.persistence.room.integration.testapp.dao.PetDao;
import android.arch.persistence.room.integration.testapp.dao.SchoolDao;
@@ -42,6 +43,7 @@
protected ToyDao mToyDao;
protected SpecificDogDao mSpecificDogDao;
protected WithClauseDao mWithClauseDao;
+ protected FunnyNamedDao mFunnyNamedDao;
@Before
public void createDb() {
@@ -55,5 +57,6 @@
mToyDao = mDatabase.getToyDao();
mSpecificDogDao = mDatabase.getSpecificDogDao();
mWithClauseDao = mDatabase.getWithClauseDao();
+ mFunnyNamedDao = mDatabase.getFunnyNamedDao();
}
}
diff --git a/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java
new file mode 100644
index 0000000..20f3c21
--- /dev/null
+++ b/room/integration-tests/testapp/src/androidTest/java/android/arch/persistence/room/integration/testapp/vo/FunnyNamedEntity.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.arch.persistence.room.integration.testapp.vo;
+
+import android.arch.persistence.room.ColumnInfo;
+import android.arch.persistence.room.Entity;
+import android.arch.persistence.room.PrimaryKey;
+
+/**
+ * An entity that was weird names
+ */
+@Entity(tableName = FunnyNamedEntity.TABLE_NAME)
+public class FunnyNamedEntity {
+ public static final String TABLE_NAME = "funny but not so funny";
+ public static final String COLUMN_ID = "_this $is id$";
+ public static final String COLUMN_VALUE = "unlikely-ΩÅŸå¨Ä±ünames";
+ @PrimaryKey(autoGenerate = true)
+ @ColumnInfo(name = COLUMN_ID)
+ private int mId;
+ @ColumnInfo(name = COLUMN_VALUE)
+ private String mValue;
+
+ public FunnyNamedEntity(int id, String value) {
+ mId = id;
+ mValue = value;
+ }
+
+ public int getId() {
+ return mId;
+ }
+
+ public void setId(int id) {
+ mId = id;
+ }
+
+ public String getValue() {
+ return mValue;
+ }
+
+ public void setValue(String value) {
+ mValue = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ FunnyNamedEntity entity = (FunnyNamedEntity) o;
+
+ if (mId != entity.mId) return false;
+ return mValue != null ? mValue.equals(entity.mValue) : entity.mValue == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mId;
+ result = 31 * result + (mValue != null ? mValue.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/CustomerViewModel.java b/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/CustomerViewModel.java
index 1f434ad..320b2cd 100644
--- a/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/CustomerViewModel.java
+++ b/room/integration-tests/testapp/src/main/java/android/arch/persistence/room/integration/testapp/CustomerViewModel.java
@@ -17,7 +17,7 @@
package android.arch.persistence.room.integration.testapp;
import android.app.Application;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.lifecycle.AndroidViewModel;
import android.arch.lifecycle.LiveData;
import android.arch.paging.DataSource;
@@ -47,7 +47,7 @@
mDatabase = Room.databaseBuilder(this.getApplication(),
SampleDatabase.class, "customerDatabase").build();
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(new Runnable() {
+ ArchTaskExecutor.getInstance().executeOnDiskIO(new Runnable() {
@Override
public void run() {
// fill with some simple data
@@ -73,7 +73,7 @@
}
void insertCustomer() {
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(new Runnable() {
+ ArchTaskExecutor.getInstance().executeOnDiskIO(new Runnable() {
@Override
public void run() {
mDatabase.getCustomerDao().insert(createCustomer());
diff --git a/room/runtime/src/main/java/android/arch/persistence/room/InvalidationTracker.java b/room/runtime/src/main/java/android/arch/persistence/room/InvalidationTracker.java
index 33bc4ed..45ec028 100644
--- a/room/runtime/src/main/java/android/arch/persistence/room/InvalidationTracker.java
+++ b/room/runtime/src/main/java/android/arch/persistence/room/InvalidationTracker.java
@@ -16,7 +16,7 @@
package android.arch.persistence.room;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.core.internal.SafeIterableMap;
import android.arch.persistence.db.SupportSQLiteDatabase;
import android.arch.persistence.db.SupportSQLiteStatement;
@@ -166,10 +166,12 @@
private static void appendTriggerName(StringBuilder builder, String tableName,
String triggerType) {
- builder.append("room_table_modification_trigger_")
+ builder.append("`")
+ .append("room_table_modification_trigger_")
.append(tableName)
.append("_")
- .append(triggerType);
+ .append(triggerType)
+ .append("`");
}
private void stopTrackingTable(SupportSQLiteDatabase writableDb, int tableId) {
@@ -192,9 +194,9 @@
appendTriggerName(stringBuilder, tableName, trigger);
stringBuilder.append(" AFTER ")
.append(trigger)
- .append(" ON ")
+ .append(" ON `")
.append(tableName)
- .append(" BEGIN INSERT OR REPLACE INTO ")
+ .append("` BEGIN INSERT OR REPLACE INTO ")
.append(UPDATE_TABLE_NAME)
.append(" VALUES(null, ")
.append(tableId)
@@ -238,7 +240,7 @@
currentObserver = mObserverMap.putIfAbsent(observer, wrapper);
}
if (currentObserver == null && mObservedTableTracker.onAdded(tableIds)) {
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mSyncTriggers);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(mSyncTriggers);
}
}
@@ -269,7 +271,7 @@
wrapper = mObserverMap.remove(observer);
}
if (wrapper != null && mObservedTableTracker.onRemoved(wrapper.mTableIds)) {
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mSyncTriggers);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(mSyncTriggers);
}
}
@@ -350,11 +352,18 @@
return;
}
- if (mDatabase.inTransaction()
- || !mPendingRefresh.compareAndSet(true, false)) {
+ if (!mPendingRefresh.compareAndSet(true, false)) {
// no pending refresh
return;
}
+
+ if (mDatabase.inTransaction()) {
+ // current thread is in a transaction. when it ends, it will invoke
+ // refreshRunnable again. mPendingRefresh is left as false on purpose
+ // so that the last transaction can flip it on again.
+ return;
+ }
+
mCleanupStatement.executeUpdateDelete();
mQueryArgs[0] = mMaxVersion;
Cursor cursor = mDatabase.query(SELECT_UPDATED_TABLES_SQL, mQueryArgs);
@@ -400,7 +409,7 @@
public void refreshVersionsAsync() {
// TODO we should consider doing this sync instead of async.
if (mPendingRefresh.compareAndSet(false, true)) {
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(mRefreshRunnable);
}
}
diff --git a/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java b/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
index d6a7f8e..cdad868 100644
--- a/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
+++ b/room/runtime/src/main/java/android/arch/persistence/room/RoomDatabase.java
@@ -16,7 +16,7 @@
package android.arch.persistence.room;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.arch.persistence.db.SimpleSQLiteQuery;
import android.arch.persistence.db.SupportSQLiteDatabase;
import android.arch.persistence.db.SupportSQLiteOpenHelper;
@@ -158,7 +158,7 @@
if (mAllowMainThreadQueries) {
return;
}
- if (AppToolkitTaskExecutor.getInstance().isMainThread()) {
+ if (ArchTaskExecutor.getInstance().isMainThread()) {
throw new IllegalStateException("Cannot access database on the main thread since"
+ " it may potentially lock the UI for a long period of time.");
}
@@ -216,7 +216,11 @@
*/
public void endTransaction() {
mOpenHelper.getWritableDatabase().endTransaction();
- mInvalidationTracker.refreshVersionsAsync();
+ if (!inTransaction()) {
+ // enqueue refresh only if we are NOT in a transaction. Otherwise, wait for the last
+ // endTransaction call to do it.
+ mInvalidationTracker.refreshVersionsAsync();
+ }
}
/**
diff --git a/room/rxjava2/src/main/java/android/arch/persistence/room/RxRoom.java b/room/rxjava2/src/main/java/android/arch/persistence/room/RxRoom.java
index adfca27..285b3f8 100644
--- a/room/rxjava2/src/main/java/android/arch/persistence/room/RxRoom.java
+++ b/room/rxjava2/src/main/java/android/arch/persistence/room/RxRoom.java
@@ -16,7 +16,7 @@
package android.arch.persistence.room;
-import android.arch.core.executor.AppToolkitTaskExecutor;
+import android.arch.core.executor.ArchTaskExecutor;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
@@ -133,7 +133,7 @@
public Disposable schedule(@NonNull Runnable run, long delay,
@NonNull TimeUnit unit) {
DisposableRunnable disposable = new DisposableRunnable(run, mDisposed);
- AppToolkitTaskExecutor.getInstance().executeOnDiskIO(run);
+ ArchTaskExecutor.getInstance().executeOnDiskIO(run);
return disposable;
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BaseRowSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BaseRowSupportFragment.java
index 7431da7..dba78da 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BaseRowSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BaseRowSupportFragment.java
@@ -14,6 +14,8 @@
package android.support.v17.leanback.app;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v17.leanback.widget.ItemBridgeAdapter;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ObjectAdapter;
@@ -75,7 +77,7 @@
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
if (savedInstanceState != null) {
mSelectedPosition = savedInstanceState.getInt(CURRENT_SELECTED_POSITION, -1);
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
index 177052d..d89cf39 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BaseSupportFragment.java
@@ -15,6 +15,8 @@
import android.annotation.SuppressLint;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v17.leanback.transition.TransitionHelper;
import android.support.v17.leanback.transition.TransitionListener;
import android.support.v17.leanback.util.StateMachine;
@@ -177,7 +179,7 @@
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mStateMachine.fireEvent(EVT_ON_CREATEVIEW);
}
diff --git a/v17/leanback/src/android/support/v17/leanback/app/BrandedSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/BrandedSupportFragment.java
index aff8c89..306e1f1 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/BrandedSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/BrandedSupportFragment.java
@@ -15,6 +15,8 @@
import android.graphics.drawable.Drawable;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.SearchOrbView;
import android.support.v17.leanback.widget.TitleHelper;
@@ -143,7 +145,7 @@
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState != null) {
mShowingTitle = savedInstanceState.getBoolean(TITLE_SHOW);
diff --git a/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
index 7a45630..56c85af 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/HeadersSupportFragment.java
@@ -20,6 +20,8 @@
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.ClassPresenterSelector;
import android.support.v17.leanback.widget.DividerPresenter;
@@ -160,7 +162,7 @@
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
final VerticalGridView listView = getVerticalGridView();
if (listView == null) {
diff --git a/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
index 9892625..51cb2de 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/OnboardingSupportFragment.java
@@ -26,6 +26,7 @@
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.ColorInt;
+import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.PagingIndicator;
@@ -350,7 +351,7 @@
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (savedInstanceState == null) {
mCurrentPageIndex = 0;
diff --git a/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragment.java
index 197e275..a8741ab 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/PlaybackSupportFragment.java
@@ -24,6 +24,8 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v17.leanback.R;
import android.support.v17.leanback.animation.LogAccelerateInterpolator;
import android.support.v17.leanback.animation.LogDecelerateInterpolator;
@@ -447,7 +449,7 @@
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// controls view are initially visible, make it invisible
// if app has called hideControlsOverlay() before view created.
diff --git a/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java b/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
index dd357ac..05e3813 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/RowsSupportFragment.java
@@ -16,6 +16,8 @@
import android.animation.TimeAnimator;
import android.animation.TimeAnimator.TimeListener;
import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.v17.leanback.R;
import android.support.v17.leanback.widget.BaseOnItemViewClickedListener;
import android.support.v17.leanback.widget.BaseOnItemViewSelectedListener;
@@ -285,7 +287,7 @@
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
if (DEBUG) Log.v(TAG, "onViewCreated");
super.onViewCreated(view, savedInstanceState);
// Align the top edge of child with id row_content.
diff --git a/v17/leanback/src/android/support/v17/leanback/app/package-info.java b/v17/leanback/src/android/support/v17/leanback/app/package-info.java
index f82570e..b736909 100644
--- a/v17/leanback/src/android/support/v17/leanback/app/package-info.java
+++ b/v17/leanback/src/android/support/v17/leanback/app/package-info.java
@@ -15,37 +15,37 @@
/**
* <p>Support classes providing high level Leanback user interface building blocks.</p>
* <p>
- * Leanback fragments are available both as platform fragments (subclassed from
- * {@link android.app.Fragment android.app.Fragment}) and as support fragments (subclassed from
- * {@link android.support.v4.app.Fragment android.support.v4.app.Fragment}). A few of the most
+ * Leanback fragments are available both as support fragments (subclassed from
+ * {@link android.support.v4.app.Fragment android.support.v4.app.Fragment}) and as platform
+ * fragments (subclassed from {@link android.app.Fragment android.app.Fragment}). A few of the most
* commonly used leanback fragments are described here.
* </p>
* <p>
- * A {@link android.support.v17.leanback.app.BrowseFragment} by default operates in the "row" mode.
- * It includes an optional “fastlane”
+ * A {@link android.support.v17.leanback.app.BrowseSupportFragment} by default operates in the "row"
+ * mode. It includes an optional “fastlane”
* navigation side panel and a list of rows, with one-to-one correspondance between each header
* in the fastlane and a row. The application supplies the
* {@link android.support.v17.leanback.widget.ObjectAdapter} containing the list of
* rows and a {@link android.support.v17.leanback.widget.PresenterSelector} of row presenters.
* </p>
* <p>
- * A {@link android.support.v17.leanback.app.BrowseFragment} also works in a "page" mode when
+ * A {@link android.support.v17.leanback.app.BrowseSupportFragment} also works in a "page" mode when
* each row of fastlane is mapped to a fragment that the app registers in
- * {@link android.support.v17.leanback.app.BrowseFragment#getMainFragmentRegistry()}.
+ * {@link android.support.v17.leanback.app.BrowseSupportFragment#getMainFragmentRegistry()}.
* </p>
* <p>
- * A {@link android.support.v17.leanback.app.DetailsFragment} will typically consist of a large
- * overview of an item at the top,
+ * A {@link android.support.v17.leanback.app.DetailsSupportFragment} will typically consist of a
+ * large overview of an item at the top,
* some actions that a user can perform, and possibly rows of additional or related items.
- * The content for this fragment is specified in the same way as for the BrowseFragment, with the
- * convention that the first element in the ObjectAdapter corresponds to the overview row.
+ * The content for this fragment is specified in the same way as for the BrowseSupportFragment, with
+ * the convention that the first element in the ObjectAdapter corresponds to the overview row.
* The {@link android.support.v17.leanback.widget.DetailsOverviewRow} and
* {@link android.support.v17.leanback.widget.FullWidthDetailsOverviewRowPresenter} provide a
* default template for this row.
* </p>
* <p>
- * A {@link android.support.v17.leanback.app.PlaybackFragment} or its subclass
- * {@link android.support.v17.leanback.app.VideoFragment} hosts
+ * A {@link android.support.v17.leanback.app.PlaybackSupportFragment} or its subclass
+ * {@link android.support.v17.leanback.app.VideoSupportFragment} hosts
* {@link android.support.v17.leanback.media.PlaybackTransportControlGlue}
* or {@link android.support.v17.leanback.media.PlaybackBannerControlGlue} with a Leanback
* look and feel. It is recommended to use an instance of
@@ -54,13 +54,13 @@
* the most commonly used controls as well as video scrubbing.
* </p>
* <p>
- * A {@link android.support.v17.leanback.app.SearchFragment} allows the developer to accept a query
- * from a user and display the results
+ * A {@link android.support.v17.leanback.app.SearchSupportFragment} allows the developer to accept a
+ * query from a user and display the results
* using the familiar list rows.
* </p>
* <p>
- * A {@link android.support.v17.leanback.app.GuidedStepFragment} is used to guide the user through a
- * decision or series of decisions.
+ * A {@link android.support.v17.leanback.app.GuidedStepSupportFragment} is used to guide the user
+ * through a decision or series of decisions.
* </p>
**/
diff --git a/v17/leanback/src/android/support/v17/leanback/package-info.java b/v17/leanback/src/android/support/v17/leanback/package-info.java
index 5259f63..80b26e9 100644
--- a/v17/leanback/src/android/support/v17/leanback/package-info.java
+++ b/v17/leanback/src/android/support/v17/leanback/package-info.java
@@ -41,13 +41,13 @@
* <p>
* Leanback contains a mixture of higher level building blocks such as Fragments in the
* {@link android.support.v17.leanback.app} package. Notable examples are the
- * {@link android.support.v17.leanback.app.BrowseFragment},
- * {@link android.support.v17.leanback.app.DetailsFragment},
- * {@link android.support.v17.leanback.app.PlaybackFragment} and the
- * {@link android.support.v17.leanback.app.GuidedStepFragment}. Helper classes are also provided
- * that work with the leanback fragments, for example the
+ * {@link android.support.v17.leanback.app.BrowseSupportFragment},
+ * {@link android.support.v17.leanback.app.DetailsSupportFragment},
+ * {@link android.support.v17.leanback.app.PlaybackSupportFragment} and the
+ * {@link android.support.v17.leanback.app.GuidedStepSupportFragment}. Helper classes are also
+ * provided that work with the leanback fragments, for example the
* {@link android.support.v17.leanback.media.PlaybackTransportControlGlue} and
- * {@link android.support.v17.leanback.app.PlaybackFragmentGlueHost}.
+ * {@link android.support.v17.leanback.app.PlaybackSupportFragmentGlueHost}.
* </p>
* <p>
* Many lower level building blocks are also provided in the {@link android.support.v17.leanback.widget} package.
diff --git a/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java b/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
index 4fb9ff8..0e7fb8f 100644
--- a/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
+++ b/v7/preference/src/android/support/v7/preference/PreferenceFragmentCompat.java
@@ -321,7 +321,7 @@
}
@Override
- public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
+ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
if (mHavePrefs) {
diff --git a/v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchHelper.java b/v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchHelper.java
index b0a2cb3..aee48df 100644
--- a/v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchHelper.java
+++ b/v7/recyclerview/src/android/support/v7/widget/helper/ItemTouchHelper.java
@@ -292,6 +292,11 @@
*/
GestureDetectorCompat mGestureDetector;
+ /**
+ * Callback for when long press occurs.
+ */
+ private ItemTouchHelperGestureListener mItemTouchHelperGestureListener;
+
private final OnItemTouchListener mOnItemTouchListener = new OnItemTouchListener() {
@Override
public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent event) {
@@ -468,7 +473,7 @@
mRecyclerView.addItemDecoration(this);
mRecyclerView.addOnItemTouchListener(mOnItemTouchListener);
mRecyclerView.addOnChildAttachStateChangeListener(this);
- initGestureDetector();
+ startGestureDetection();
}
private void destroyCallbacks() {
@@ -485,14 +490,23 @@
mOverdrawChild = null;
mOverdrawChildPosition = -1;
releaseVelocityTracker();
+ stopGestureDetection();
}
- private void initGestureDetector() {
- if (mGestureDetector != null) {
- return;
- }
+ private void startGestureDetection() {
+ mItemTouchHelperGestureListener = new ItemTouchHelperGestureListener();
mGestureDetector = new GestureDetectorCompat(mRecyclerView.getContext(),
- new ItemTouchHelperGestureListener());
+ mItemTouchHelperGestureListener);
+ }
+
+ private void stopGestureDetection() {
+ if (mItemTouchHelperGestureListener != null) {
+ mItemTouchHelperGestureListener.doNotReactToLongPress();
+ mItemTouchHelperGestureListener = null;
+ }
+ if (mGestureDetector != null) {
+ mGestureDetector = null;
+ }
}
private void getSelectedDxDy(float[] outPosition) {
@@ -2242,9 +2256,33 @@
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
+ /**
+ * Whether to execute code in response to the the invoking of
+ * {@link ItemTouchHelperGestureListener#onLongPress(MotionEvent)}.
+ *
+ * It is necessary to control this here because
+ * {@link GestureDetector.SimpleOnGestureListener} can only be set on a
+ * {@link GestureDetector} in a GestureDetector's constructor, a GestureDetector will call
+ * onLongPress if an {@link MotionEvent#ACTION_DOWN} event is not followed by another event
+ * that would cancel it (like {@link MotionEvent#ACTION_UP} or
+ * {@link MotionEvent#ACTION_CANCEL}), the long press responding to the long press event
+ * needs to be cancellable to prevent unexpected behavior.
+ *
+ * @see #doNotReactToLongPress()
+ */
+ private boolean mShouldReactToLongPress = true;
+
ItemTouchHelperGestureListener() {
}
+ /**
+ * Call to prevent executing code in response to
+ * {@link ItemTouchHelperGestureListener#onLongPress(MotionEvent)} being called.
+ */
+ void doNotReactToLongPress() {
+ mShouldReactToLongPress = false;
+ }
+
@Override
public boolean onDown(MotionEvent e) {
return true;
@@ -2252,6 +2290,9 @@
@Override
public void onLongPress(MotionEvent e) {
+ if (!mShouldReactToLongPress) {
+ return;
+ }
View child = findChildView(e);
if (child != null) {
ViewHolder vh = mRecyclerView.getChildViewHolder(child);
diff --git a/v7/recyclerview/tests/src/android/support/v7/util/TouchUtils.java b/v7/recyclerview/tests/src/android/support/v7/util/TouchUtils.java
index 02099ba..1a64e3c 100644
--- a/v7/recyclerview/tests/src/android/support/v7/util/TouchUtils.java
+++ b/v7/recyclerview/tests/src/android/support/v7/util/TouchUtils.java
@@ -142,13 +142,6 @@
inst.sendPointerSync(event);
inst.waitForIdleSync();
- eventTime = SystemClock.uptimeMillis();
- final int touchSlop = ViewConfiguration.get(v.getContext()).getScaledTouchSlop();
- event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE,
- x + touchSlop / 2, y + touchSlop / 2, 0);
- inst.sendPointerSync(event);
- inst.waitForIdleSync();
-
try {
Thread.sleep((long) (ViewConfiguration.getLongPressTimeout() * 1.5f));
} catch (InterruptedException e) {
diff --git a/v7/recyclerview/tests/src/android/support/v7/widget/helper/ItemTouchHelperTest.java b/v7/recyclerview/tests/src/android/support/v7/widget/helper/ItemTouchHelperTest.java
index 18af47b..090ea69 100644
--- a/v7/recyclerview/tests/src/android/support/v7/widget/helper/ItemTouchHelperTest.java
+++ b/v7/recyclerview/tests/src/android/support/v7/widget/helper/ItemTouchHelperTest.java
@@ -32,11 +32,13 @@
import android.support.test.filters.Suppress;
import android.support.test.runner.AndroidJUnit4;
import android.support.testutils.PollingCheck;
+import android.support.v4.util.Pair;
import android.support.v7.util.TouchUtils;
import android.support.v7.widget.BaseRecyclerViewInstrumentationTest;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.WrappedRecyclerView;
import android.view.Gravity;
+import android.view.View;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -48,26 +50,27 @@
@RunWith(AndroidJUnit4.class)
public class ItemTouchHelperTest extends BaseRecyclerViewInstrumentationTest {
- TestAdapter mAdapter;
-
- TestLayoutManager mLayoutManager;
+ private static class RecyclerViewState {
+ public TestAdapter mAdapter;
+ public TestLayoutManager mLayoutManager;
+ public WrappedRecyclerView mWrappedRecyclerView;
+ }
private LoggingCalback mCalback;
private LoggingItemTouchHelper mItemTouchHelper;
- private WrappedRecyclerView mWrappedRecyclerView;
-
private Boolean mSetupRTL;
public ItemTouchHelperTest() {
super(false);
}
- private RecyclerView setup(int dragDirs, int swipeDirs) throws Throwable {
- mWrappedRecyclerView = inflateWrappedRV();
- mAdapter = new TestAdapter(10);
- mLayoutManager = new TestLayoutManager() {
+ private RecyclerViewState setupRecyclerView() throws Throwable {
+ RecyclerViewState rvs = new RecyclerViewState();
+ rvs.mWrappedRecyclerView = inflateWrappedRV();
+ rvs.mAdapter = new TestAdapter(10);
+ rvs.mLayoutManager = new TestLayoutManager() {
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
detachAndScrapAttachedViews(recycler);
@@ -85,19 +88,24 @@
return false;
}
};
- mWrappedRecyclerView.setFakeRTL(mSetupRTL);
- mWrappedRecyclerView.setAdapter(mAdapter);
- mWrappedRecyclerView.setLayoutManager(mLayoutManager);
+ rvs.mWrappedRecyclerView.setFakeRTL(mSetupRTL);
+ rvs.mWrappedRecyclerView.setAdapter(rvs.mAdapter);
+ rvs.mWrappedRecyclerView.setLayoutManager(rvs.mLayoutManager);
+ return rvs;
+ }
+
+ private RecyclerViewState setupItemTouchHelper(final RecyclerViewState rvs, int dragDirs,
+ int swipeDirs) throws Throwable {
mCalback = new LoggingCalback(dragDirs, swipeDirs);
mItemTouchHelper = new LoggingItemTouchHelper(mCalback);
mActivityRule.runOnUiThread(new Runnable() {
@Override
public void run() {
- mItemTouchHelper.attachToRecyclerView(mWrappedRecyclerView);
+ mItemTouchHelper.attachToRecyclerView(rvs.mWrappedRecyclerView);
}
});
- return mWrappedRecyclerView;
+ return rvs;
}
@Test
@@ -136,11 +144,60 @@
basicSwipeTest(END, START | END, -getActivity().getWindow().getDecorView().getWidth());
}
+ @Test
+ public void attachToNullRecycleViewDuringLongPress() throws Throwable {
+ final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), END, 0);
+ rvs.mLayoutManager.expectLayouts(1);
+ setRecyclerView(rvs.mWrappedRecyclerView);
+ rvs.mLayoutManager.waitForLayout(1);
+
+ final RecyclerView.ViewHolder target = mRecyclerView
+ .findViewHolderForAdapterPosition(1);
+ target.itemView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ mItemTouchHelper.attachToRecyclerView(null);
+ return false;
+ }
+ });
+ TouchUtils.longClickView(getInstrumentation(), target.itemView);
+ }
+
+ @Test
+ public void attachToAnotherRecycleViewDuringLongPress() throws Throwable {
+ final RecyclerViewState rvs2 = setupRecyclerView();
+ rvs2.mLayoutManager.expectLayouts(1);
+ mActivityRule.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ getActivity().getContainer().addView(rvs2.mWrappedRecyclerView);
+ }
+ });
+ rvs2.mLayoutManager.waitForLayout(1);
+
+ final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), END, 0);
+ rvs.mLayoutManager.expectLayouts(1);
+ setRecyclerView(rvs.mWrappedRecyclerView);
+ rvs.mLayoutManager.waitForLayout(1);
+
+ final RecyclerView.ViewHolder target = mRecyclerView
+ .findViewHolderForAdapterPosition(1);
+ target.itemView.setOnLongClickListener(new View.OnLongClickListener() {
+ @Override
+ public boolean onLongClick(View v) {
+ mItemTouchHelper.attachToRecyclerView(rvs2.mWrappedRecyclerView);
+ return false;
+ }
+ });
+ TouchUtils.longClickView(getInstrumentation(), target.itemView);
+ assertEquals(0, mCalback.mHasDragFlag.size());
+ }
+
public void basicSwipeTest(int dir, int swipeDirs, int targetX) throws Throwable {
- final RecyclerView recyclerView = setup(0, swipeDirs);
- mLayoutManager.expectLayouts(1);
- setRecyclerView(recyclerView);
- mLayoutManager.waitForLayout(1);
+ final RecyclerViewState rvs = setupItemTouchHelper(setupRecyclerView(), 0, swipeDirs);
+ rvs.mLayoutManager.expectLayouts(1);
+ setRecyclerView(rvs.mWrappedRecyclerView);
+ rvs.mLayoutManager.waitForLayout(1);
final RecyclerView.ViewHolder target = mRecyclerView
.findViewHolderForAdapterPosition(1);
@@ -158,9 +215,9 @@
assertEquals(1, mItemTouchHelper.mRecoverAnimations.size());
assertEquals(1, mItemTouchHelper.mPendingCleanup.size());
// get rid of the view
- mLayoutManager.expectLayouts(1);
- mAdapter.deleteAndNotify(1, 1);
- mLayoutManager.waitForLayout(1);
+ rvs.mLayoutManager.expectLayouts(1);
+ rvs.mAdapter.deleteAndNotify(1, 1);
+ rvs.mLayoutManager.waitForLayout(1);
waitForAnimations();
assertEquals(0, mItemTouchHelper.mRecoverAnimations.size());
assertEquals(0, mItemTouchHelper.mPendingCleanup.size());
@@ -181,6 +238,8 @@
private List<RecyclerView.ViewHolder> mCleared = new ArrayList<RecyclerView.ViewHolder>();
+ public List<Pair<RecyclerView, RecyclerView.ViewHolder>> mHasDragFlag = new ArrayList<>();
+
LoggingCalback(int dragDirs, int swipeDirs) {
super(dragDirs, swipeDirs);
}
@@ -212,6 +271,12 @@
mCleared.add(viewHolder);
}
+ @Override
+ boolean hasDragFlag(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
+ mHasDragFlag.add(new Pair<>(recyclerView, viewHolder));
+ return super.hasDragFlag(recyclerView, viewHolder);
+ }
+
public SwipeRecord getSwipe(RecyclerView.ViewHolder vh) {
for (SwipeRecord swipe : mSwipeRecords) {
if (swipe.viewHolder == vh) {