Add support for ListenableFutures for @RawQuery

By Accepting SupportSQLiteQuery instead of RoomSqliteQuery, @RawQuery can be supported. @RawQuery is used in conjunction with SimpleSQLiteQuery which is another implementation of SupportSQLiteQuery.

Test: RawQueryTest
BUG: 288945320
Change-Id: I00d4b706cfbe1b7d76535dec41cc31e02bc8259f
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/RawDao.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/RawDao.java
index e3638e4..12b0dfb 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/RawDao.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/dao/RawDao.java
@@ -26,6 +26,8 @@
 import androidx.room.integration.testapp.vo.UserAndPet;
 import androidx.sqlite.db.SupportSQLiteQuery;
 
+import com.google.common.util.concurrent.ListenableFuture;
+
 import java.util.Date;
 import java.util.List;
 
@@ -41,6 +43,9 @@
     User getUser(SupportSQLiteQuery query);
 
     @RawQuery
+    ListenableFuture<User> getUserListenableFuture(SupportSQLiteQuery query);
+
+    @RawQuery
     UserAndPet getUserAndPet(SupportSQLiteQuery query);
 
     @RawQuery
diff --git a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RawQueryTest.java b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RawQueryTest.java
index 10cdd5b..3cb7715 100644
--- a/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RawQueryTest.java
+++ b/room/integration-tests/testapp/src/androidTest/java/androidx/room/integration/testapp/test/RawQueryTest.java
@@ -42,6 +42,7 @@
 
 import java.util.Arrays;
 import java.util.List;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
@@ -117,6 +118,17 @@
     }
 
     @Test
+    public void listenableFuture_supportSql() throws ExecutionException,
+            InterruptedException {
+        User user = TestUtil.createUser(3);
+        mUserDao.insert(user);
+        SimpleSQLiteQuery query = new SimpleSQLiteQuery("SELECT * FROM User WHERE mId = ?",
+                new Object[]{3});
+        User received = mRawDao.getUserListenableFuture(query).get();
+        assertThat(received, is(user));
+    }
+
+    @Test
     public void embedded() {
         User user = TestUtil.createUser(3);
         Pet[] pets = TestUtil.createPetsForUser(3, 1, 1);
diff --git a/room/room-guava/api/restricted_current.txt b/room/room-guava/api/restricted_current.txt
index 76401e6..858f7b9 100644
--- a/room/room-guava/api/restricted_current.txt
+++ b/room/room-guava/api/restricted_current.txt
@@ -5,6 +5,7 @@
     method public static <T> com.google.common.util.concurrent.ListenableFuture<T!> createListenableFuture(androidx.room.RoomDatabase, boolean, java.util.concurrent.Callable<T!>);
     method public static <T> com.google.common.util.concurrent.ListenableFuture<T!>! createListenableFuture(androidx.room.RoomDatabase!, boolean, java.util.concurrent.Callable<T!>!, androidx.room.RoomSQLiteQuery!, boolean);
     method public static <T> com.google.common.util.concurrent.ListenableFuture<T!> createListenableFuture(androidx.room.RoomDatabase, boolean, java.util.concurrent.Callable<T!>, androidx.room.RoomSQLiteQuery, boolean, android.os.CancellationSignal?);
+    method public static <T> com.google.common.util.concurrent.ListenableFuture<T!> createListenableFuture(androidx.room.RoomDatabase, boolean, java.util.concurrent.Callable<T!>, androidx.sqlite.db.SupportSQLiteQuery, boolean, android.os.CancellationSignal?);
     method @Deprecated public static <T> com.google.common.util.concurrent.ListenableFuture<T!> createListenableFuture(androidx.room.RoomDatabase, java.util.concurrent.Callable<T!>);
     method @Deprecated public static <T> com.google.common.util.concurrent.ListenableFuture<T!>! createListenableFuture(androidx.room.RoomDatabase!, java.util.concurrent.Callable<T!>!, androidx.room.RoomSQLiteQuery!, boolean);
     method @Deprecated public static <T> com.google.common.util.concurrent.ListenableFuture<T!>! createListenableFuture(java.util.concurrent.Callable<T!>!, androidx.room.RoomSQLiteQuery!, boolean);
diff --git a/room/room-guava/src/main/java/androidx/room/guava/GuavaRoom.java b/room/room-guava/src/main/java/androidx/room/guava/GuavaRoom.java
index b47dc4b..31f7e76 100644
--- a/room/room-guava/src/main/java/androidx/room/guava/GuavaRoom.java
+++ b/room/room-guava/src/main/java/androidx/room/guava/GuavaRoom.java
@@ -27,6 +27,7 @@
 import androidx.room.RoomDatabase;
 import androidx.room.RoomSQLiteQuery;
 import androidx.sqlite.db.SupportSQLiteCompat;
+import androidx.sqlite.db.SupportSQLiteQuery;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
@@ -112,10 +113,28 @@
                 cancellationSignal);
     }
 
+    /**
+     * Returns a {@link ListenableFuture<T>} created by submitting the input {@code callable} to
+     * {@link RoomDatabase}'s {@link java.util.concurrent.Executor}.
+     */
+    @NonNull
+    @SuppressLint("LambdaLast")
+    public static <T> ListenableFuture<T> createListenableFuture(
+            final @NonNull RoomDatabase roomDatabase,
+            final boolean inTransaction,
+            final @NonNull Callable<T> callable,
+            final @NonNull SupportSQLiteQuery query,
+            final boolean releaseQuery,
+            final @Nullable CancellationSignal cancellationSignal) {
+        return createListenableFuture(
+                getExecutor(roomDatabase, inTransaction), callable, query, releaseQuery,
+                cancellationSignal);
+    }
+
     private static <T> ListenableFuture<T> createListenableFuture(
             final Executor executor,
             final Callable<T> callable,
-            final RoomSQLiteQuery query,
+            final SupportSQLiteQuery query,
             final boolean releaseQuery,
             final @Nullable CancellationSignal cancellationSignal) {
 
@@ -135,7 +154,9 @@
             future.addListener(new Runnable() {
                 @Override
                 public void run() {
-                    query.release();
+                    if (query instanceof RoomSQLiteQuery) {
+                        ((RoomSQLiteQuery) query).release();
+                    }
                 }
             }, sDirectExecutor);
         }