1 /* Copyright 2020 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 #include "tensorflow/lite/experimental/acceleration/compatibility/android_info.h"
16 
17 #include <iostream>
18 #include <string>
19 
20 #include "absl/status/status.h"
21 
22 #ifdef __ANDROID__
23 #include <sys/system_properties.h>
24 #endif  // __ANDROID__
25 
26 namespace {
GetPropertyValue(const std::string & property)27 std::string GetPropertyValue(const std::string& property) {
28 #ifdef __ANDROID__
29   char value[PROP_VALUE_MAX];
30   __system_property_get(property.c_str(), value);
31   return std::string(value);
32 #else   // !__ANDROID__
33   return std::string();
34 #endif  // __ANDROID__
35 }
36 }  // namespace
37 
38 namespace tflite {
39 namespace acceleration {
40 
RequestAndroidInfo(AndroidInfo * info_out)41 absl::Status RequestAndroidInfo(AndroidInfo* info_out) {
42   if (!info_out) {
43     return absl::InvalidArgumentError("info_out may not be null");
44   }
45   info_out->android_sdk_version = GetPropertyValue("ro.build.version.sdk");
46   info_out->device = GetPropertyValue("ro.product.device");
47   info_out->model = GetPropertyValue("ro.product.model");
48   info_out->manufacturer = GetPropertyValue("ro.product.manufacturer");
49 #ifdef __ANDROID__
50   // Based on
51   // https://github.com/flutter/plugins/blob/master/packages/device_info/device_info/android/src/main/java/io/flutter/plugins/deviceinfo/MethodCallHandlerImpl.java
52   // + QUMA detection (system properties return empty) and qemu detection
53   // (ro.kernel.qemu).
54   std::string brand = GetPropertyValue("ro.product.brand");
55   const std::string& device = info_out->device;
56   std::string fingerprint = GetPropertyValue("ro.build.fingerprint");
57   std::string hardware = GetPropertyValue("ro.hardware");
58   const std::string& model = info_out->model;
59   const std::string& manufacturer = info_out->manufacturer;
60   std::string product = GetPropertyValue("ro.build.product");
61   std::string ro_kernel_qemu = GetPropertyValue("ro.kernel.qemu");
62   info_out->is_emulator =
63       ((brand.find("generic") == 0 && device.find("generic") == 0) ||  // NOLINT
64        fingerprint.find("generic") == 0 ||                             // NOLINT
65        fingerprint.find("unknown") == 0 ||                             // NOLINT
66        hardware.find("goldfish") != std::string::npos ||               // NOLINT
67        hardware.find("ranchu") != std::string::npos ||                 // NOLINT
68        model.find("google_sdk") != std::string::npos ||                // NOLINT
69        model.find("Emulator") != std::string::npos ||                  // NOLINT
70        model.find("Android SDK built for x86") !=                      // NOLINT
71            std::string::npos ||                                        // NOLINT
72        manufacturer.find("Genymotion") != std::string::npos ||         // NOLINT
73        product.find("sdk_google") != std::string::npos ||              // NOLINT
74        product.find("google_sdk") != std::string::npos ||              // NOLINT
75        product.find("sdk") != std::string::npos ||                     // NOLINT
76        product.find("sdk_x86") != std::string::npos ||                 // NOLINT
77        product.find("vbox86p") != std::string::npos ||                 // NOLINT
78        product.find("emulator") != std::string::npos ||                // NOLINT
79        product.find("simulator") != std::string::npos ||               // NOLINT
80        ro_kernel_qemu == "1" ||                                        // NOLINT
81        info_out->android_sdk_version.empty());                         // NOLINT
82 #else
83   info_out->is_emulator = false;
84 #endif
85 
86   return absl::OkStatus();
87 }
88 
89 }  // namespace acceleration
90 }  // namespace tflite
91