Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 1 | // Copyright 2019 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include <sstream> |
| 6 | |
| 7 | #include "base/android/jni_android.h" |
| 8 | #include "base/files/file.h" |
| 9 | #include "base/files/file_path.h" |
| 10 | #include "base/files/file_util.h" |
| 11 | #include "base/files/memory_mapped_file.h" |
Xi Han | 095f3934 | 2019-08-08 20:00:54 | [diff] [blame] | 12 | #include "base/metrics/field_trial.h" |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 13 | #include "base/metrics/persistent_histogram_allocator.h" |
| 14 | #include "base/system/sys_info.h" |
Andrew Grieve | 4a42c22e | 2019-06-24 16:14:29 | [diff] [blame] | 15 | #include "chrome/android/test_support_jni_headers/ServicificationBackgroundService_jni.h" |
Xi Han | b06d11b | 2020-04-02 14:37:16 | [diff] [blame] | 16 | #include "chrome/browser/android/metrics/uma_session_stats.h" |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 17 | #include "components/metrics/persistent_system_profile.h" |
Xi Han | 095f3934 | 2019-08-08 20:00:54 | [diff] [blame] | 18 | #include "components/variations/active_field_trials.h" |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 19 | #include "third_party/metrics_proto/system_profile.pb.h" |
| 20 | |
| 21 | // Verifies that the memory-mapped file for persistent histograms data exists |
| 22 | // and contains a valid SystemProfile. |
| 23 | jboolean |
| 24 | JNI_ServicificationBackgroundService_TestPersistentHistogramsOnDiskSystemProfile( |
| 25 | JNIEnv* env) { |
| 26 | base::GlobalHistogramAllocator* allocator = |
| 27 | base::GlobalHistogramAllocator::Get(); |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 28 | if (!allocator) { |
| 29 | LOG(ERROR) << "The GlobalHistogramAllocator is null!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 30 | return false; |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 31 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 32 | |
| 33 | const base::FilePath& persistent_file_path = |
| 34 | allocator->GetPersistentLocation(); |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 35 | if (persistent_file_path.empty()) { |
| 36 | LOG(ERROR) << "The path of the persistent file is empty!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 37 | return false; |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 38 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 39 | |
| 40 | base::File file(persistent_file_path, |
| 41 | base::File::FLAG_OPEN | base::File::FLAG_READ); |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 42 | if (!file.IsValid()) { |
| 43 | LOG(ERROR) << "The persistent file isn't valid!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 44 | return false; |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 45 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 46 | |
| 47 | std::unique_ptr<base::MemoryMappedFile> mapped(new base::MemoryMappedFile()); |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 48 | if (!mapped->Initialize(std::move(file), base::MemoryMappedFile::READ_ONLY)) { |
| 49 | LOG(ERROR) << "Fails to Initialize the memory mapped file!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 50 | return false; |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 51 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 52 | |
| 53 | if (!base::FilePersistentMemoryAllocator::IsFileAcceptable( |
| 54 | *mapped, true /* read_only */)) { |
Xi Han | b2371fe | 2020-07-15 20:05:59 | [diff] [blame] | 55 | LOG(ERROR) << "The memory mapped file isn't acceptable!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 56 | return false; |
| 57 | } |
| 58 | |
| 59 | // Map the file and validate it. |
| 60 | std::unique_ptr<base::FilePersistentMemoryAllocator> memory_allocator = |
| 61 | std::make_unique<base::FilePersistentMemoryAllocator>( |
| 62 | std::move(mapped), 0, 0, base::StringPiece(), /* read_only */ true); |
| 63 | if (memory_allocator->GetMemoryState() == |
| 64 | base::PersistentMemoryAllocator::MEMORY_DELETED) { |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 65 | LOG(ERROR) << "The memory allocator state shouldn't be MEMORY_DELETED!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 66 | return false; |
| 67 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 68 | |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 69 | if (memory_allocator->IsCorrupt()) { |
| 70 | LOG(ERROR) << "The memory allocator is corrupt!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 71 | return false; |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 72 | } |
| 73 | |
| 74 | if (!metrics::PersistentSystemProfile::HasSystemProfile(*memory_allocator)) { |
| 75 | LOG(ERROR) << "There isn't a System Profile!"; |
| 76 | return false; |
| 77 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 78 | |
| 79 | metrics::SystemProfileProto system_profile_proto; |
| 80 | if (!metrics::PersistentSystemProfile::GetSystemProfile( |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 81 | *memory_allocator, &system_profile_proto)) { |
| 82 | LOG(ERROR) << "Failed to get the System Profile!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 83 | return false; |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 84 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 85 | |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 86 | if (!system_profile_proto.has_os()) { |
| 87 | LOG(ERROR) << "The os info isn't set!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 88 | return false; |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 89 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 90 | |
| 91 | const metrics::SystemProfileProto_OS& os = system_profile_proto.os(); |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 92 | if (!os.has_version()) { |
| 93 | LOG(ERROR) << "The os version isn't set!"; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 94 | return false; |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 95 | } |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 96 | |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 97 | if (base::SysInfo::OperatingSystemVersion().compare(os.version()) != 0) { |
| 98 | LOG(ERROR) << "The os version doesn't match!"; |
Xi Han | 095f3934 | 2019-08-08 20:00:54 | [diff] [blame] | 99 | return false; |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 100 | } |
Xi Han | 095f3934 | 2019-08-08 20:00:54 | [diff] [blame] | 101 | |
| 102 | std::vector<variations::ActiveGroupId> field_trial_ids; |
| 103 | variations::GetFieldTrialActiveGroupIds("", &field_trial_ids); |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 104 | int expected_size = static_cast<int>(field_trial_ids.size()); |
Xi Han | 095f3934 | 2019-08-08 20:00:54 | [diff] [blame] | 105 | |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 106 | // The active field trial "Foo" is guaranteed in the list. |
| 107 | if (expected_size <= 0) { |
| 108 | LOG(ERROR) << "Expect at least one active field trial!"; |
Xi Han | 095f3934 | 2019-08-08 20:00:54 | [diff] [blame] | 109 | return false; |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 110 | } |
Xi Han | 095f3934 | 2019-08-08 20:00:54 | [diff] [blame] | 111 | |
Xi Han | a0fb771 | 2019-08-13 17:19:35 | [diff] [blame] | 112 | if (system_profile_proto.field_trial_size() != expected_size) { |
| 113 | LOG(ERROR) << "The size of field trials recorded in the System Profile" |
| 114 | << " doesn't match the size of active field trials!"; |
| 115 | return false; |
| 116 | } |
| 117 | |
| 118 | return true; |
Xi Han | 59bb8c2 | 2019-05-23 21:05:50 | [diff] [blame] | 119 | } |
Xi Han | b06d11b | 2020-04-02 14:37:16 | [diff] [blame] | 120 | |
| 121 | // Returns whether a background session has started. |
| 122 | jboolean JNI_ServicificationBackgroundService_IsBackgroundSessionStart( |
| 123 | JNIEnv* env) { |
| 124 | return UmaSessionStats::IsBackgroundSessionStartForTesting(); |
| 125 | } |