Split GPU Compatibility Lib into two.

PiperOrigin-RevId: 324867524
Change-Id: Ibf5403a725aee72ebeba4d6681660c289326eb69
diff --git a/tensorflow/lite/delegates/gpu/java/src/main/native/BUILD b/tensorflow/lite/delegates/gpu/java/src/main/native/BUILD
index 00b56bb..7b340e2 100644
--- a/tensorflow/lite/delegates/gpu/java/src/main/native/BUILD
+++ b/tensorflow/lite/delegates/gpu/java/src/main/native/BUILD
@@ -30,7 +30,7 @@
         "//tensorflow/lite/delegates/gpu/gl:egl_environment",
         "//tensorflow/lite/delegates/gpu/gl:request_gpu_info",
         "//tensorflow/lite/experimental/acceleration/compatibility:android_info",
-        "//tensorflow/lite/experimental/acceleration/compatibility:gpu_compatibility",
+        "//tensorflow/lite/experimental/acceleration/compatibility:gpu_compatibility_recommender",
         "//tensorflow/lite/java/jni",
         "@com_google_absl//absl/status",
     ],
diff --git a/tensorflow/lite/delegates/gpu/java/src/main/native/gpu_delegate_jni.cc b/tensorflow/lite/delegates/gpu/java/src/main/native/gpu_delegate_jni.cc
index d31d058..c457110 100644
--- a/tensorflow/lite/delegates/gpu/java/src/main/native/gpu_delegate_jni.cc
+++ b/tensorflow/lite/delegates/gpu/java/src/main/native/gpu_delegate_jni.cc
@@ -21,7 +21,7 @@
 #include "tensorflow/lite/delegates/gpu/gl/egl_environment.h"
 #include "tensorflow/lite/delegates/gpu/gl/request_gpu_info.h"
 #include "tensorflow/lite/experimental/acceleration/compatibility/android_info.h"
-#include "tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.h"
+#include "tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -74,13 +74,13 @@
   }
 
   bool IsDelegateSupportedOnThisDevice() {
-    return compatibility_list_.Includes(android_info_, gpu_info_);
+    return compatibility_recommender_.Includes(android_info_, gpu_info_);
   }
 
  private:
   tflite::acceleration::AndroidInfo android_info_;
   tflite::gpu::GpuInfo gpu_info_;
-  tflite::acceleration::GPUCompatibilityList compatibility_list_;
+  tflite::acceleration::GPUCompatibilityRecommender compatibility_recommender_;
 };
 }  // namespace
 
diff --git a/tensorflow/lite/experimental/acceleration/compatibility/BUILD b/tensorflow/lite/experimental/acceleration/compatibility/BUILD
index 78a9d2e..6adb6da 100644
--- a/tensorflow/lite/experimental/acceleration/compatibility/BUILD
+++ b/tensorflow/lite/experimental/acceleration/compatibility/BUILD
@@ -152,7 +152,6 @@
         ":android_info",
         ":database_fbs",
         ":devicedb",
-        "//tensorflow/lite/delegates/gpu:delegate",
         "//tensorflow/lite/delegates/gpu/common:gpu_info",
         "@com_google_absl//absl/status",
         "@com_google_absl//absl/strings",
@@ -160,4 +159,41 @@
     ],
 )
 
+cc_test(
+    name = "gpu_compatibility_test",
+    srcs = ["gpu_compatibility_test.cc"],
+    deps = [
+        ":gpu_compatibility",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "gpu_compatibility_recommender",
+    srcs = [
+        "gpu_compatibility_recommender.cc",
+    ],
+    hdrs = [
+        "gpu_compatibility_recommender.h",
+    ],
+    deps = [
+        ":android_info",
+        ":gpu_compatibility",
+        "//tensorflow/lite/delegates/gpu:delegate",
+        "//tensorflow/lite/delegates/gpu/common:gpu_info",
+    ],
+)
+
+cc_test(
+    name = "gpu_compatibility_recommender_test",
+    srcs = ["gpu_compatibility_recommender_test.cc"],
+    tags = ["notap"],  # Needs to be built with --copt=-DCL_DELEGATE_NO_GL
+    deps = [
+        ":gpu_compatibility_recommender",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
 tflite_portable_test_suite()
diff --git a/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.cc b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.cc
index e04f5d1..1911d26 100644
--- a/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.cc
+++ b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.cc
@@ -89,13 +89,8 @@
   return variables[gpu::kStatus] == std::string(gpu::kStatusSupported);
 }
 
-TfLiteGpuDelegateOptionsV2 GPUCompatibilityList::GetBestOptionsFor(
-    const AndroidInfo& /* android_info */,
-    const ::tflite::gpu::GpuInfo& /* gpu_info */) const {
-  // This method is for forwards-compatibility: the list may later include
-  // information about which backend to choose (OpenGL/OpenCL/Vulkan) or other
-  // options.
-  return TfLiteGpuDelegateOptionsV2Default();
+bool GPUCompatibilityList::IsDatabaseLoaded() const {
+  return database_ != nullptr;
 }
 
 }  // namespace acceleration
diff --git a/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.h b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.h
index f975fe0..873151d 100644
--- a/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.h
+++ b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.h
@@ -19,7 +19,6 @@
 #include <string>
 
 #include "tensorflow/lite/delegates/gpu/common/gpu_info.h"
-#include "tensorflow/lite/delegates/gpu/delegate.h"
 #include "tensorflow/lite/experimental/acceleration/compatibility/android_info.h"
 #include "tensorflow/lite/experimental/acceleration/compatibility/devicedb.h"
 
@@ -32,54 +31,41 @@
 // Android version, OpenGL ES version, GPU chipset etc. The support is based on
 // measure stability, correctness and peformance. For more detail see README.md.
 //
+// Reads from the flatbuffer.
 // Example usage:
-//   tflite::Interpreter* interpreter = ... ;
+//   tflite::acceleration::GPUCompatibilityList list;
 //   tflite::acceleration::AndroidInfo android_info;
 //   tflite::gpu::GpuInfo gpu_info;
-//   EXPECT_OK(tflite::acceleration::RequestAndroidInfo(&android_info));
-//   EXPECT_OK(tflite::gpu::gl::EglEnvironment::NewEglEnvironment(&env));
-//   EXPECT_OK(tflite::gpu::gl::RequestGpuInfo(&tflite_gpu_info));
-//   tflite::acceleration::GPUCompatibilityList list;
-//   TfLiteDelegate* gpu_delegate = nullptr;
-//   TfLiteGpuDelegateOptions gpu_options;
-//   if (list.Includes(android_info, gpu_info)) {
-//     gpu_options = list.BestOptionsFor(android_info, gpu_info);
-//     gpu_delegate = TfLiteGpuDelegateCreate(&gpu_options);
-//     EXPECT_EQ(interpreter->ModifyGraphWithDelegate(gpu_delegate), TfLiteOk);
-//   } else {
-//     // Fallback path.
+//   ...
+//   if(list.Includes(android_info, gpu_info)){
+//    // SUPPORTED.
+//   } else{
+//    // UNSUPPORTED.
 //   }
 class GPUCompatibilityList {
  public:
   // Construct list from bundled data.
   GPUCompatibilityList();
+  // Constructs list from the given flatbuffer.
+  explicit GPUCompatibilityList(
+      const unsigned char* compatibility_list_flatbuffer);
   // Returns true if the provided device specs are supported by the database.
   bool Includes(const AndroidInfo& android_info,
                 const ::tflite::gpu::GpuInfo& gpu_info) const;
-
-  // Returns the best TfLiteGpuDelegateOptionsV2 for the provided device specs
-  // based on the database. The output can be modified as desired before passing
-  // to delegate creation.
-  TfLiteGpuDelegateOptionsV2 GetBestOptionsFor(
-      const AndroidInfo& android_info,
-      const ::tflite::gpu::GpuInfo& gpu_info) const;
-
   // Convert android_info and gpu_info into a set of variables used for querying
   // the list, and update variables from list data. See variables.h
   // and devicedb.h for more information.
   std::map<std::string, std::string> CalculateVariables(
       const AndroidInfo& android_info,
       const ::tflite::gpu::GpuInfo& gpu_info) const;
-
   GPUCompatibilityList(const GPUCompatibilityList&) = delete;
   GPUCompatibilityList& operator=(const GPUCompatibilityList&) = delete;
+  // Indicates if the database is loaded.
+  bool IsDatabaseLoaded() const;
 
  protected:
-  explicit GPUCompatibilityList(
-      const unsigned char* compatibility_list_flatbuffer);
   const DeviceDatabase* database_;
 };
-
 }  // namespace acceleration
 }  // namespace tflite
 
diff --git a/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.cc b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.cc
new file mode 100644
index 0000000..1b62591
--- /dev/null
+++ b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.cc
@@ -0,0 +1,30 @@
+/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+
+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.
+==============================================================================*/
+#include "tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.h"
+
+namespace tflite {
+namespace acceleration {
+
+TfLiteGpuDelegateOptionsV2 GPUCompatibilityRecommender::GetBestOptionsFor(
+    const AndroidInfo& /* android_info */,
+    const ::tflite::gpu::GpuInfo& /* gpu_info */) const {
+  // This method is for forwards-compatibility: the list may later include
+  // information about which backend to choose (OpenGL/OpenCL/Vulkan) or other
+  // options.
+  return TfLiteGpuDelegateOptionsV2Default();
+}
+
+}  // namespace acceleration
+}  // namespace tflite
diff --git a/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.h b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.h
new file mode 100644
index 0000000..4443cfd
--- /dev/null
+++ b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.h
@@ -0,0 +1,64 @@
+/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+
+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.
+==============================================================================*/
+#ifndef TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_COMPATIBILITY_GPU_COMPATIBILITY_RECOMMENDER_H_
+#define TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_COMPATIBILITY_GPU_COMPATIBILITY_RECOMMENDER_H_
+
+#include "tensorflow/lite/delegates/gpu/common/gpu_info.h"
+#include "tensorflow/lite/delegates/gpu/delegate.h"
+#include "tensorflow/lite/experimental/acceleration/compatibility/android_info.h"
+#include "tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.h"
+
+namespace tflite {
+namespace acceleration {
+
+// This class recommends best TfLiteGPU delegate options for Android devices.
+//
+// Example usage:
+//   tflite::Interpreter* interpreter = ... ;
+//   tflite::acceleration::AndroidInfo android_info;
+//   tflite::gpu::GpuInfo gpu_info;
+//   CHECK(tflite::acceleration::RequestAndroidInfo(&android_info));
+//   CHECK(tflite::gpu::gl::EglEnvironment::NewEglEnvironment(&env));
+//   CHECK(tflite::gpu::gl::RequestGpuInfo(&tflite_gpu_info));
+//   tflite::acceleration::GPUCompatibilityRecommender recommender;
+//   TfLiteDelegate* gpu_delegate = nullptr;
+//   TfLiteGpuDelegateOptions gpu_options;
+//   if (list.Includes(android_info, gpu_info)) {
+//     gpu_options = recommender.BestOptionsFor(android_info, gpu_info);
+//     gpu_delegate = TfLiteGpuDelegateCreate(&gpu_options);
+//     CHECK_EQ(interpreter->ModifyGraphWithDelegate(gpu_delegate), TfLiteOk);
+//   } else {
+//     // Fallback path.
+//   }
+
+class GPUCompatibilityRecommender : public GPUCompatibilityList {
+ public:
+  GPUCompatibilityRecommender() {}
+  GPUCompatibilityRecommender(const GPUCompatibilityRecommender&) = delete;
+  GPUCompatibilityRecommender& operator=(const GPUCompatibilityRecommender&) =
+      delete;
+
+  // Returns the best TfLiteGpuDelegateOptionsV2 for the provided device specs
+  // based on the database. The output can be modified as desired before passing
+  // to delegate creation.
+  TfLiteGpuDelegateOptionsV2 GetBestOptionsFor(
+      const AndroidInfo& android_info,
+      const ::tflite::gpu::GpuInfo& gpu_info) const;
+};
+
+}  // namespace acceleration
+}  // namespace tflite
+
+#endif  // TENSORFLOW_LITE_EXPERIMENTAL_ACCELERATION_COMPATIBILITY_GPU_COMPATIBILITY_RECOMMENDER_H_
diff --git a/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender_test.cc b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender_test.cc
new file mode 100644
index 0000000..ebf793d
--- /dev/null
+++ b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender_test.cc
@@ -0,0 +1,100 @@
+/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+
+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.
+==============================================================================*/
+#include "tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_recommender.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+class GPUCompatibilityRecommenderTest : public ::testing::Test {
+ protected:
+  GPUCompatibilityRecommenderTest() {
+    recommender_ =
+        absl::make_unique<tflite::acceleration::GPUCompatibilityRecommender>();
+  }
+
+  std::unique_ptr<tflite::acceleration::GPUCompatibilityRecommender>
+      recommender_;
+};
+
+TEST_F(GPUCompatibilityRecommenderTest, Load) {
+  EXPECT_TRUE(recommender_->IsDatabaseLoaded());
+}
+
+TEST_F(GPUCompatibilityRecommenderTest, ReturnsSupportedForFullMatch) {
+  tflite::acceleration::AndroidInfo android_info = {
+      .android_sdk_version = "28",
+      .model = "redmi_note_7G960F",
+      .device = "lavender",
+      .manufacturer = "xiaomi"};
+  tflite::gpu::GpuInfo tflite_gpu_info = {
+      .renderer_name = "adreno_(tm)_512",
+      .major_version = 3,
+      .minor_version = 2,
+  };
+  EXPECT_TRUE(recommender_->Includes(android_info, tflite_gpu_info));
+}
+
+TEST_F(GPUCompatibilityRecommenderTest, ReturnsUnsupported) {
+  tflite::acceleration::AndroidInfo android_info = {.android_sdk_version = "28",
+                                                    .model = "sm_g960f",
+                                                    .device = "starlte",
+                                                    .manufacturer = "samsung"};
+  tflite::gpu::GpuInfo tflite_gpu_info = {
+      .renderer_name = "mali_g72",
+      .major_version = 3,
+      .minor_version = 2,
+  };
+
+  EXPECT_FALSE(recommender_->Includes(android_info, tflite_gpu_info));
+}
+
+TEST_F(GPUCompatibilityRecommenderTest, MissingInfoReturnsUnsupported) {
+  tflite::acceleration::AndroidInfo android_info = {.android_sdk_version = "23",
+                                                    .model = "sm_g532f",
+                                                    .device = "grandpplte",
+                                                    .manufacturer = "samsung"};
+  tflite::gpu::GpuInfo tflite_gpu_info = {
+      .renderer_name = "mali_t720",
+      .major_version = 3,
+      .minor_version = 1,
+  };
+  EXPECT_FALSE(recommender_->Includes(android_info, tflite_gpu_info));
+}
+
+TEST_F(GPUCompatibilityRecommenderTest, ReturnsDefaultOptions) {
+  tflite::acceleration::AndroidInfo android_info;
+  tflite::gpu::GpuInfo tflite_gpu_info;
+  auto default_options = TfLiteGpuDelegateOptionsV2Default();
+  auto best_options =
+      recommender_->GetBestOptionsFor(android_info, tflite_gpu_info);
+  EXPECT_EQ(best_options.is_precision_loss_allowed,
+            default_options.is_precision_loss_allowed);
+  EXPECT_EQ(best_options.inference_preference,
+            default_options.inference_preference);
+  EXPECT_EQ(best_options.inference_priority1,
+            default_options.inference_priority1);
+  EXPECT_EQ(best_options.inference_priority2,
+            default_options.inference_priority2);
+  EXPECT_EQ(best_options.inference_priority3,
+            default_options.inference_priority3);
+  EXPECT_EQ(best_options.experimental_flags,
+            default_options.experimental_flags);
+  EXPECT_EQ(best_options.max_delegated_partitions,
+            default_options.max_delegated_partitions);
+}
+
+}  // namespace
diff --git a/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_test.cc b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_test.cc
new file mode 100644
index 0000000..d300867
--- /dev/null
+++ b/tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility_test.cc
@@ -0,0 +1,61 @@
+/* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
+
+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.
+==============================================================================*/
+#include "tensorflow/lite/experimental/acceleration/compatibility/gpu_compatibility.h"
+
+#include <memory>
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+class GPUCompatibilityTest : public ::testing::Test {
+ protected:
+  GPUCompatibilityTest() {
+    list_ = absl::make_unique<tflite::acceleration::GPUCompatibilityList>();
+  }
+
+  std::unique_ptr<tflite::acceleration::GPUCompatibilityList> list_;
+};
+
+TEST_F(GPUCompatibilityTest, Load) { EXPECT_TRUE(list_->IsDatabaseLoaded()); }
+
+TEST_F(GPUCompatibilityTest, ReturnsSupportedForFullMatch) {
+  tflite::acceleration::AndroidInfo android_info = {.android_sdk_version = "27",
+                                                    .model = "cph1803",
+                                                    .device = "cph1803",
+                                                    .manufacturer = "Oppo"};
+  tflite::gpu::GpuInfo tflite_gpu_info = {
+      .renderer_name = "Adreno (TM) 506",
+      .major_version = 3,
+      .minor_version = 2,
+  };
+  EXPECT_TRUE(list_->Includes(android_info, tflite_gpu_info));
+}
+
+TEST_F(GPUCompatibilityTest, ReturnsUnsupportedForFullMatch) {
+  tflite::acceleration::AndroidInfo android_info = {.android_sdk_version = "28",
+                                                    .model = "SM-G960F",
+                                                    .device = "starlte",
+                                                    .manufacturer = "Samsung"};
+  tflite::gpu::GpuInfo tflite_gpu_info = {
+      .renderer_name = "Mali-G72",
+      .major_version = 3,
+      .minor_version = 2,
+  };
+  EXPECT_FALSE(list_->Includes(android_info, tflite_gpu_info));
+}
+
+}  // namespace