|  | // Copyright 2019 The Chromium Authors | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include <sstream> | 
|  |  | 
|  | #include "base/android/jni_android.h" | 
|  | #include "base/files/file.h" | 
|  | #include "base/files/file_path.h" | 
|  | #include "base/files/file_util.h" | 
|  | #include "base/files/memory_mapped_file.h" | 
|  | #include "base/metrics/field_trial.h" | 
|  | #include "base/metrics/persistent_histogram_allocator.h" | 
|  | #include "base/system/sys_info.h" | 
|  | #include "chrome/android/test_support_jni_headers/ServicificationBackgroundService_jni.h" | 
|  | #include "chrome/browser/android/metrics/uma_session_stats.h" | 
|  | #include "components/metrics/persistent_system_profile.h" | 
|  | #include "components/variations/active_field_trials.h" | 
|  | #include "third_party/metrics_proto/system_profile.pb.h" | 
|  |  | 
|  | // Verifies that the memory-mapped file for persistent histograms data exists | 
|  | // and contains a valid SystemProfile. | 
|  | jboolean | 
|  | JNI_ServicificationBackgroundService_TestPersistentHistogramsOnDiskSystemProfile( | 
|  | JNIEnv* env) { | 
|  | base::GlobalHistogramAllocator* allocator = | 
|  | base::GlobalHistogramAllocator::Get(); | 
|  | if (!allocator) { | 
|  | LOG(ERROR) << "The GlobalHistogramAllocator is null!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | const base::FilePath& persistent_file_path = | 
|  | allocator->GetPersistentLocation(); | 
|  | if (persistent_file_path.empty()) { | 
|  | LOG(ERROR) << "The path of the persistent file is empty!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | base::File file(persistent_file_path, | 
|  | base::File::FLAG_OPEN | base::File::FLAG_READ); | 
|  | if (!file.IsValid()) { | 
|  | LOG(ERROR) << "The persistent file isn't valid!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<base::MemoryMappedFile> mapped(new base::MemoryMappedFile()); | 
|  | if (!mapped->Initialize(std::move(file), base::MemoryMappedFile::READ_ONLY)) { | 
|  | LOG(ERROR) << "Fails to Initialize the memory mapped file!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (!base::FilePersistentMemoryAllocator::IsFileAcceptable( | 
|  | *mapped, true /* read_only */)) { | 
|  | LOG(ERROR) << "The memory mapped file isn't acceptable!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Map the file and validate it. | 
|  | std::unique_ptr<base::FilePersistentMemoryAllocator> memory_allocator = | 
|  | std::make_unique<base::FilePersistentMemoryAllocator>( | 
|  | std::move(mapped), 0, 0, base::StringPiece(), /* read_only */ true); | 
|  | if (memory_allocator->GetMemoryState() == | 
|  | base::PersistentMemoryAllocator::MEMORY_DELETED) { | 
|  | LOG(ERROR) << "The memory allocator state shouldn't be MEMORY_DELETED!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (memory_allocator->IsCorrupt()) { | 
|  | LOG(ERROR) << "The memory allocator is corrupt!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (!metrics::PersistentSystemProfile::HasSystemProfile(*memory_allocator)) { | 
|  | LOG(ERROR) << "There isn't a System Profile!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | metrics::SystemProfileProto system_profile_proto; | 
|  | if (!metrics::PersistentSystemProfile::GetSystemProfile( | 
|  | *memory_allocator, &system_profile_proto)) { | 
|  | LOG(ERROR) << "Failed to get the System Profile!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (!system_profile_proto.has_os()) { | 
|  | LOG(ERROR) << "The os info isn't set!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | const metrics::SystemProfileProto_OS& os = system_profile_proto.os(); | 
|  | if (!os.has_version()) { | 
|  | LOG(ERROR) << "The os version isn't set!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (base::SysInfo::OperatingSystemVersion().compare(os.version()) != 0) { | 
|  | LOG(ERROR) << "The os version doesn't match!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | std::vector<variations::ActiveGroupId> field_trial_ids; | 
|  | variations::GetFieldTrialActiveGroupIds("", &field_trial_ids); | 
|  | int expected_size = static_cast<int>(field_trial_ids.size()); | 
|  |  | 
|  | // The active field trial "Foo" is guaranteed in the list. | 
|  | if (expected_size <= 0) { | 
|  | LOG(ERROR) << "Expect at least one active field trial!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (system_profile_proto.field_trial_size() != expected_size) { | 
|  | LOG(ERROR) << "The size of field trials recorded in the System Profile" | 
|  | << " doesn't match the size of active field trials!"; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // Returns whether a background session has started. | 
|  | jboolean JNI_ServicificationBackgroundService_IsBackgroundSessionStart( | 
|  | JNIEnv* env) { | 
|  | return UmaSessionStats::IsBackgroundSessionStartForTesting(); | 
|  | } |