1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/android/device_info.h"
#include <string>
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/compiler_specific.h"
#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
// Must come after all headers that specialize FromJniType() / ToJniType().
#include "base/build_info_jni/DeviceInfo_jni.h"
#if __ANDROID_API__ >= 29
// .aidl based NDK generation is only available when our min SDK level is 29 or
// higher.
#include "aidl/org/chromium/base/IDeviceInfo.h"
using aidl::org::chromium::base::IDeviceInfo;
#endif
namespace base::android::device_info {
namespace {
#if __ANDROID_API__ < 29
struct IDeviceInfo {
std::string gmsVersionCode;
bool isAutomotive;
bool isDesktop;
bool isFoldable;
bool isTv;
// Available only on Android T+.
int32_t vulkanDeqpLevel;
bool isXr;
bool wasLaunchedOnLargeDisplay;
};
#endif
static std::optional<IDeviceInfo>& get_holder() {
static base::NoDestructor<std::optional<IDeviceInfo>> holder;
return *holder;
}
IDeviceInfo& get_device_info() {
std::optional<IDeviceInfo>& holder = get_holder();
if (!holder.has_value()) {
Java_DeviceInfo_nativeReadyForFields(AttachCurrentThread());
}
return *holder;
}
} // namespace
void Set(const IDeviceInfo& info) {
static base::NoDestructor<base::Lock> lock;
base::AutoLock l(*lock);
std::optional<IDeviceInfo>& holder = get_holder();
holder.emplace(info);
}
static void JNI_DeviceInfo_FillFields(JNIEnv* env,
std::string& gmsVersionCode,
bool isTV,
bool isAutomotive,
bool isFoldable,
bool isDesktop,
jint vulkanDeqpLevel,
bool isXr,
bool wasLaunchedOnLargeDisplay) {
Set(IDeviceInfo{.gmsVersionCode = gmsVersionCode,
.isAutomotive = isAutomotive,
.isDesktop = isDesktop,
.isFoldable = isFoldable,
.isTv = isTV,
.vulkanDeqpLevel = vulkanDeqpLevel,
.isXr = isXr,
.wasLaunchedOnLargeDisplay = wasLaunchedOnLargeDisplay});
}
const std::string& gms_version_code() {
return get_device_info().gmsVersionCode;
}
void set_gms_version_code_for_test(const std::string& gms_version_code) {
get_device_info().gmsVersionCode = gms_version_code;
Java_DeviceInfo_setGmsVersionCodeForTest(AttachCurrentThread(),
gms_version_code);
}
bool is_tv() {
return get_device_info().isTv;
}
bool is_automotive() {
return get_device_info().isAutomotive;
}
bool is_foldable() {
return get_device_info().isFoldable;
}
bool is_desktop() {
return get_device_info().isDesktop;
}
// Available only on Android T+.
int32_t vulkan_deqp_level() {
return get_device_info().vulkanDeqpLevel;
}
bool is_xr() {
return get_device_info().isXr;
}
// Roughly matches the check logic in device_form_factor.h to see if the device
// is a tablet (based on mostly elimination of other possible form-factors and
// screen-width). Where possible, prefer using device_form_factor.h (runtime
// check) as a first choice, but fall back to this if not feasible.
bool is_tablet() {
return was_launched_on_large_display() && !is_tv() && !is_automotive() &&
!is_desktop() && !is_xr();
}
// This returns the cached value during initial startup. If you need this
// evaluated at runtime, then use device_form_factor Additionally, this differs
// from device_form_factor in that it does not guarantee that the Android
// resource (-sw600) is respected.
bool was_launched_on_large_display() {
return get_device_info().wasLaunchedOnLargeDisplay;
}
std::string device_name() {
JNIEnv* env = base::android::AttachCurrentThread();
return base::android::ConvertJavaStringToUTF8(
env, Java_DeviceInfo_getDeviceName(env));
}
void set_is_xr_for_testing() {
Java_DeviceInfo_setIsXrForTesting(AttachCurrentThread(), true); // IN-TEST
get_holder().reset();
}
void reset_is_xr_for_testing() {
Java_DeviceInfo_resetIsXrForTesting(AttachCurrentThread()); // IN-TEST
get_holder().reset();
}
} // namespace base::android::device_info
DEFINE_JNI(DeviceInfo)
|