Merge "libchrome uprev to r1230523" into main
diff --git a/BASE_VER b/BASE_VER
index 4f8f708..86ca885 100644
--- a/BASE_VER
+++ b/BASE_VER
@@ -1 +1 @@
-1227295
\ No newline at end of file
+1230523
diff --git a/BUILD.gn b/BUILD.gn
index b8c3205..7b3202c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -672,6 +672,7 @@
"base/task/thread_pool.cc",
"base/task/thread_pool/delayed_task_manager.cc",
"base/task/thread_pool/environment_config.cc",
+ "base/task/thread_pool/job_task_source_old.cc",
"base/task/thread_pool/job_task_source.cc",
"base/task/thread_pool/pooled_parallel_task_runner.cc",
"base/task/thread_pool/pooled_sequenced_task_runner.cc",
diff --git a/base/allocator/dispatcher/internal/dispatch_data.h b/base/allocator/dispatcher/internal/dispatch_data.h
index cad5be9..732b048 100644
--- a/base/allocator/dispatcher/internal/dispatch_data.h
+++ b/base/allocator/dispatcher/internal/dispatch_data.h
@@ -55,4 +55,4 @@
} // namespace base::allocator::dispatcher::internal
-#endif
+#endif // BASE_ALLOCATOR_DISPATCHER_INTERNAL_DISPATCH_DATA_H_
diff --git a/base/allocator/dispatcher/internal/tools.h b/base/allocator/dispatcher/internal/tools.h
index e270f48..692232e 100644
--- a/base/allocator/dispatcher/internal/tools.h
+++ b/base/allocator/dispatcher/internal/tools.h
@@ -26,4 +26,4 @@
} // namespace base::allocator::dispatcher::internal
-#endif // BASE_ALLOCATOR_DISPATCHER_INTERNAL_DISPATCHER_H_
\ No newline at end of file
+#endif // BASE_ALLOCATOR_DISPATCHER_INTERNAL_TOOLS_H_
diff --git a/base/allocator/dispatcher/testing/tools.h b/base/allocator/dispatcher/testing/tools.h
index 4eb6fcd..a9b5fbd 100644
--- a/base/allocator/dispatcher/testing/tools.h
+++ b/base/allocator/dispatcher/testing/tools.h
@@ -47,4 +47,4 @@
} // namespace base::allocator::dispatcher::testing
-#endif
+#endif // BASE_ALLOCATOR_DISPATCHER_TESTING_TOOLS_H_
diff --git a/base/allocator/partition_alloc_features.cc b/base/allocator/partition_alloc_features.cc
index 382618f..ab0086c 100644
--- a/base/allocator/partition_alloc_features.cc
+++ b/base/allocator/partition_alloc_features.cc
@@ -118,6 +118,10 @@
const base::FeatureParam<int> kPartitionAllocSchedulerLoopQuarantineCapacity{
&kPartitionAllocSchedulerLoopQuarantine,
"PartitionAllocSchedulerLoopQuarantineCapacity", 0};
+
+BASE_FEATURE(kPartitionAllocZappingByFreeFlags,
+ "PartitionAllocZappingByFreeFlags",
+ FEATURE_DISABLED_BY_DEFAULT);
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
BASE_FEATURE(kPartitionAllocBackupRefPtr,
diff --git a/base/allocator/partition_alloc_features.h b/base/allocator/partition_alloc_features.h
index a72d35e..30a93af 100644
--- a/base/allocator/partition_alloc_features.h
+++ b/base/allocator/partition_alloc_features.h
@@ -74,6 +74,8 @@
BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocSchedulerLoopQuarantine);
extern const BASE_EXPORT base::FeatureParam<int>
kPartitionAllocSchedulerLoopQuarantineCapacity;
+
+BASE_EXPORT BASE_DECLARE_FEATURE(kPartitionAllocZappingByFreeFlags);
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
enum class BackupRefPtrEnabledProcesses {
diff --git a/base/allocator/partition_alloc_support.cc b/base/allocator/partition_alloc_support.cc
index d0e9bda..a4f9642 100644
--- a/base/allocator/partition_alloc_support.cc
+++ b/base/allocator/partition_alloc_support.cc
@@ -1104,6 +1104,8 @@
const size_t scheduler_loop_quarantine_capacity_in_bytes =
static_cast<size_t>(
base::features::kPartitionAllocSchedulerLoopQuarantineCapacity.Get());
+ const bool zapping_by_free_flags = base::FeatureList::IsEnabled(
+ base::features::kPartitionAllocZappingByFreeFlags);
bool enable_memory_tagging = false;
partition_alloc::TagViolationReportingMode memory_tagging_reporting_mode =
@@ -1179,7 +1181,8 @@
allocator_shim::UseDedicatedAlignedPartition(
brp_config.use_dedicated_aligned_partition),
brp_config.ref_count_size, bucket_distribution,
- scheduler_loop_quarantine_capacity_in_bytes);
+ scheduler_loop_quarantine_capacity_in_bytes,
+ allocator_shim::ZappingByFreeFlags(zapping_by_free_flags));
const uint32_t extras_size = allocator_shim::GetMainPartitionRootExtrasSize();
// As per description, extras are optional and are expected not to
diff --git a/base/allocator/partition_allocator/partition_alloc.gni b/base/allocator/partition_allocator/partition_alloc.gni
index 1471292..447fe26 100644
--- a/base/allocator/partition_allocator/partition_alloc.gni
+++ b/base/allocator/partition_allocator/partition_alloc.gni
@@ -10,6 +10,15 @@
import("//build/config/features.gni")
}
+# PartitionAlloc have limited support for MSVC's cl.exe compiler. It can only
+# access the generate "buildflags" and the "raw_ptr" definitions implemented
+# with RawPtrNoOpImpl. Everything else is considered not supported.
+#
+# Since there are no other good ways to detect MSVC's cl.exe, we are reusing the
+# same definition used by Chrome in //base/BUILD.gn. See
+# https://crbug.com/988071.
+is_clang_or_gcc = is_clang || !is_win
+
# Whether 64-bit pointers are used.
# A static_assert in partition_alloc_config.h verifies that.
if (is_nacl) {
@@ -28,10 +37,8 @@
# Causes all the allocations to be routed via allocator_shim.cc. Usually,
# the allocator shim will, in turn, route them to Partition Alloc, but
# other allocators are also supported by the allocator shim.
- use_allocator_shim = use_allocator_shim_default
-}
+ use_allocator_shim = use_allocator_shim_default && is_clang_or_gcc
-declare_args() {
# Whether PartitionAlloc should be available for use or not.
# true makes PartitionAlloc linked to the executable or shared library and
# makes it available for use. It doesn't mean that the default allocator
@@ -49,7 +56,18 @@
# and doesn't wish to incur the library size increase (crbug.com/674570).
# 2. On NaCl (through this declaration), where PartitionAlloc doesn't
# build at all.
- use_partition_alloc = !is_nacl
+ use_partition_alloc = !is_nacl && is_clang_or_gcc
+}
+
+if (!is_clang_or_gcc) {
+ assert(!use_partition_alloc,
+ "PartitionAlloc's allocator does not support this compiler")
+ assert(!use_allocator_shim,
+ "PartitionAlloc's allocator shim does not support this compiler")
+}
+
+if (is_nacl) {
+ assert(!use_partition_alloc, "PartitionAlloc doesn't build on NaCl")
}
declare_args() {
@@ -217,11 +235,7 @@
# We want to provide assertions that guard against inconsistent build
# args, but there is no point in having them fire if we're not building
# PartitionAlloc at all. If `use_partition_alloc` is false, we jam all
-# related args to `false`. The prime example is NaCl, where
-# PartitionAlloc doesn't build at all.
-if (is_nacl) {
- assert(!use_partition_alloc, "PartitionAlloc doesn't build on NaCl")
-}
+# related args to `false`.
if (!use_partition_alloc) {
use_partition_alloc_as_malloc = false
enable_backup_ref_ptr_support = false
diff --git a/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.cc b/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.cc
index a562e43..b906ee3 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/gwp_asan_support.cc
@@ -24,9 +24,11 @@
std::vector<uint16_t>& free_list) {
PA_CHECK(slot_count > 0);
- constexpr PartitionOptions kConfig{
- .backup_ref_ptr = PartitionOptions::kEnabled,
- };
+ constexpr PartitionOptions kConfig = []() {
+ PartitionOptions opts;
+ opts.backup_ref_ptr = PartitionOptions::kEnabled;
+ return opts;
+ }();
static internal::base::NoDestructor<PartitionRoot> root(kConfig);
const size_t kSlotSize = 2 * internal::SystemPageSize();
diff --git a/base/allocator/partition_allocator/src/partition_alloc/hardening_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/hardening_unittest.cc
index 8a80371..d489787 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/hardening_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/hardening_unittest.cc
@@ -27,9 +27,9 @@
std::string important_data("very important");
char* to_corrupt = const_cast<char*>(important_data.c_str());
- PartitionRoot root(PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- });
+ PartitionOptions opts;
+ opts.aligned_alloc = PartitionOptions::kAllowed;
+ PartitionRoot root(opts);
root.UncapEmptySlotSpanMemoryForTesting();
const size_t kAllocSize = 100;
@@ -52,9 +52,9 @@
std::string important_data("very important");
char* to_corrupt = const_cast<char*>(important_data.c_str());
- PartitionRoot root(PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- });
+ PartitionOptions opts;
+ opts.aligned_alloc = PartitionOptions::kAllowed;
+ PartitionRoot root(opts);
root.UncapEmptySlotSpanMemoryForTesting();
const size_t kAllocSize = 100;
@@ -73,9 +73,9 @@
}
TEST(HardeningTest, MetadataPointerCrashing) {
- PartitionRoot root(PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- });
+ PartitionOptions opts;
+ opts.aligned_alloc = PartitionOptions::kAllowed;
+ PartitionRoot root(opts);
root.UncapEmptySlotSpanMemoryForTesting();
const size_t kAllocSize = 100;
@@ -100,9 +100,9 @@
#if !BUILDFLAG(IS_ANDROID)
TEST(HardeningTest, SuccessfulCorruption) {
- PartitionRoot root(PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- });
+ PartitionOptions opts;
+ opts.aligned_alloc = PartitionOptions::kAllowed;
+ PartitionRoot root(opts);
root.UncapEmptySlotSpanMemoryForTesting();
uintptr_t* zero_vector = reinterpret_cast<uintptr_t*>(
diff --git a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc
index 100e316..ccd1a67 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.cc
@@ -6,7 +6,6 @@
#include "partition_alloc/partition_page.h"
#include "partition_alloc/partition_root.h"
-#include "partition_alloc/partition_stats.h"
namespace partition_alloc::internal {
@@ -17,124 +16,93 @@
}
} // namespace
-template <typename QuarantineEntry, size_t CapacityCount>
-uint32_t LightweightQuarantineList<QuarantineEntry, CapacityCount>::Quarantine(
- QuarantineEntry&& entry) {
- const auto entry_size = GetObjectSize(entry.GetObject());
+template <size_t QuarantineCapacityCount>
+bool LightweightQuarantineBranch<QuarantineCapacityCount>::Quarantine(
+ void* object) {
+ const auto entry_size = GetObjectSize(object);
const size_t capacity_in_bytes =
- capacity_in_bytes_.load(std::memory_order_relaxed);
- if (capacity_in_bytes < entry_size) {
- // Even this single entry does not fit within the capacity.
- root_->Free(entry.GetObject());
- quarantine_miss_count_.fetch_add(1u, std::memory_order_relaxed);
- return kInvalidEntryID;
- }
+ root_.capacity_in_bytes_.load(std::memory_order_relaxed);
- size_t entry_id;
{
// It may be possible to narrow down the locked section, but we will not
// make any detailed adjustments for now, as we aim to create a lock-free
// implementation by having a thread-local list.
ScopedGuard guard(lock_);
- // Dequarantine some entries as required.
- size_t count = count_.load(std::memory_order_acquire);
- size_t size_in_bytes = size_in_bytes_.load(std::memory_order_acquire);
- while (kCapacityCount < count + 1 ||
- capacity_in_bytes < size_in_bytes + entry_size) {
- PA_DCHECK(0 < count);
- // As quarantined entries are shuffled, picking last entry is equivalent
- // to picking random entry.
- void* to_free =
- slots_[entry_ids_[count - 1] & kSlotIndexMask].GetObject();
- size_t to_free_size = GetObjectSize(to_free);
-
- PA_DCHECK(to_free);
- // We don't guarantee the deferred `Free()` has the same `FreeFlags`.
- root_->Free<FreeFlags::kNoHooks>(to_free);
-
- // Increment the counter embedded in the entry id.
- // This helps to identify the entry associated with this slot.
- entry_ids_[count - 1] += kCapacityCount;
- if (PA_UNLIKELY(entry_ids_[count - 1] == kInvalidEntryID)) {
- // Increment again so that it does not collide with the invalid id.
- entry_ids_[count - 1] += kCapacityCount;
- }
-
- count--;
- size_in_bytes -= to_free_size;
- // Contents of `slots_[...]` remains as is, to keep the free-time
- // information as much as possible.
+ const size_t size_in_bytes_held_by_others =
+ root_.size_in_bytes_.load(std::memory_order_relaxed) -
+ branch_size_in_bytes_;
+ if (capacity_in_bytes < size_in_bytes_held_by_others + entry_size) {
+ // Even if this branch dequarantines all entries held by it, this entry
+ // cannot fit within the capacity.
+ root_.allocator_root_.template Free<FreeFlags::kNoHooks>(object);
+ root_.quarantine_miss_count_.fetch_add(1u, std::memory_order_relaxed);
+ return false;
}
- // Obtain an entry id.
- PA_DCHECK(count < kCapacityCount);
- entry_id = entry_ids_[count];
- count++;
- size_in_bytes += entry_size;
+ // Dequarantine some entries as required.
+ PurgeInternal(kQuarantineCapacityCount - 1, capacity_in_bytes - entry_size);
// Update stats (locked).
- count_.store(count, std::memory_order_release);
- size_in_bytes_.store(size_in_bytes, std::memory_order_release);
+ branch_count_++;
+ PA_DCHECK(branch_count_ <= kQuarantineCapacityCount);
+ branch_size_in_bytes_ += entry_size;
+ PA_DCHECK(branch_size_in_bytes_ <= capacity_in_bytes);
- // Swap randomly so that the quarantine indices remain shuffled.
+ slots_[branch_count_ - 1] = object;
+
+ // Swap randomly so that the quarantine list remain shuffled.
// This is not uniformly random, but sufficiently random.
- const size_t random_index = random_.RandUint32() % count;
- std::swap(entry_ids_[random_index], entry_ids_[count - 1]);
-
- auto& slot = slots_[entry_id & kSlotIndexMask];
- slot.entry_id = entry_id;
- slot.entry = std::move(entry);
+ const size_t random_index = random_.RandUint32() % branch_count_;
+ std::swap(slots_[random_index], slots_[branch_count_ - 1]);
}
// Update stats (not locked).
- cumulative_count_.fetch_add(1, std::memory_order_relaxed);
- cumulative_size_in_bytes_.fetch_add(entry_size, std::memory_order_relaxed);
- return entry_id;
+ root_.count_.fetch_add(1, std::memory_order_relaxed);
+ root_.size_in_bytes_.fetch_add(entry_size, std::memory_order_relaxed);
+ root_.cumulative_count_.fetch_add(1, std::memory_order_relaxed);
+ root_.cumulative_size_in_bytes_.fetch_add(entry_size,
+ std::memory_order_relaxed);
+ return true;
}
-template <typename QuarantineEntry, size_t CapacityCount>
-void LightweightQuarantineList<QuarantineEntry, CapacityCount>::AccumulateStats(
- LightweightQuarantineStats& stats) const {
- stats.count += count_.load(std::memory_order_relaxed);
- stats.size_in_bytes += size_in_bytes_.load(std::memory_order_relaxed);
- stats.cumulative_count += cumulative_count_.load(std::memory_order_relaxed);
- stats.cumulative_size_in_bytes +=
- cumulative_size_in_bytes_.load(std::memory_order_relaxed);
- stats.quarantine_miss_count +=
- quarantine_miss_count_.load(std::memory_order_relaxed);
-}
+template <size_t QuarantineCapacityCount>
+void LightweightQuarantineBranch<QuarantineCapacityCount>::PurgeInternal(
+ size_t target_branch_count,
+ size_t target_size_in_bytes) {
+ size_t size_in_bytes = root_.size_in_bytes_.load(std::memory_order_acquire);
+ int64_t freed_count = 0;
+ int64_t freed_size_in_bytes = 0;
-template <typename QuarantineEntry, size_t CapacityCount>
-bool LightweightQuarantineList<QuarantineEntry, CapacityCount>::
- IsQuarantinedForTesting(void* object) {
- ScopedGuard guard(lock_);
- for (size_t i = 0; i < count_; i++) {
- if (slots_[entry_ids_[i] & kSlotIndexMask].GetObject() == object) {
- return true;
- }
- }
- return false;
-}
+ // Dequarantine some entries as required.
+ while (branch_count_ && (target_branch_count < branch_count_ ||
+ target_size_in_bytes < size_in_bytes)) {
+ // As quarantined entries are shuffled, picking last entry is equivalent
+ // to picking random entry.
+ void* to_free = slots_[branch_count_ - 1];
+ size_t to_free_size = GetObjectSize(to_free);
-template <typename QuarantineEntry, size_t CapacityCount>
-void LightweightQuarantineList<QuarantineEntry, CapacityCount>::Purge() {
- ScopedGuard guard(lock_);
-
- size_t count = count_.load(std::memory_order_acquire);
- while (0 < count) {
- void* to_free = slots_[entry_ids_[count - 1] & kSlotIndexMask].GetObject();
PA_DCHECK(to_free);
- root_->Free<FreeFlags::kNoHooks>(to_free);
- count--;
+ // We don't guarantee the deferred `Free()` has the same `FreeFlags`.
+ root_.allocator_root_.template Free<FreeFlags::kNoHooks>(to_free);
+
+ freed_count++;
+ freed_size_in_bytes += to_free_size;
+
+ branch_count_--;
+ size_in_bytes -= to_free_size;
}
- count_.store(0, std::memory_order_release);
- size_in_bytes_.store(0, std::memory_order_release);
- std::iota(entry_ids_.begin(), entry_ids_.end(), 0);
+
+ branch_size_in_bytes_ -= freed_size_in_bytes;
+ root_.count_.fetch_sub(freed_count, std::memory_order_relaxed);
+ root_.size_in_bytes_.fetch_sub(freed_size_in_bytes,
+ std::memory_order_release);
}
-template class PA_EXPORT_TEMPLATE_DEFINE(PA_COMPONENT_EXPORT(PARTITION_ALLOC))
- LightweightQuarantineList<LightweightQuarantineEntry, 1024>;
+#define EXPORT_TEMPLATE \
+ template class PA_EXPORT_TEMPLATE_DEFINE(PA_COMPONENT_EXPORT(PARTITION_ALLOC))
+EXPORT_TEMPLATE LightweightQuarantineBranch<1024>;
+#undef EXPORT_TEMPLATE
} // namespace partition_alloc::internal
diff --git a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h
index a611cec..af38406 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine.h
@@ -13,7 +13,22 @@
// - Don't use quarantined objects' payload - available for zapping
// - Don't allocate heap memory.
// - Flexible to support several applications
-// - TODO(crbug.com/1462223): Implement Miracle Object quarantine with LQ.
+//
+// `LightweightQuarantineRoot` represents one quarantine system
+// (e.g. scheduler loop quarantine).
+// `LightweightQuarantineBranch` provides a quarantine request interface.
+// It belongs to a `LightweightQuarantineRoot` and there can be multiple
+// instances (e.g. one per thread). By having one branch per thread, it requires
+// no lock for faster quarantine.
+// ┌────────────────────────────┐
+// │PartitionRoot │
+// └┬──────────────────────────┬┘
+// ┌▽────────────────────────┐┌▽────────────────────┐
+// │LQRoot 1 ││LQRoot 2 │
+// └┬───────────┬───────────┬┘└──────────────┬──┬──┬┘
+// ┌▽─────────┐┌▽─────────┐┌▽─────────┐ ▽ ▽ ▽
+// │LQBranch 1││LQBranch 2││LQBranch 3│
+// └──────────┘└──────────┘└──────────┘
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_LIGHTWEIGHT_QUARANTINE_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_LIGHTWEIGHT_QUARANTINE_H_
@@ -22,14 +37,13 @@
#include <array>
#include <atomic>
#include <limits>
-#include <numeric>
#include <type_traits>
-#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/export_template.h"
#include "partition_alloc/partition_alloc_base/rand_util.h"
#include "partition_alloc/partition_alloc_base/thread_annotations.h"
#include "partition_alloc/partition_lock.h"
+#include "partition_alloc/partition_stats.h"
namespace partition_alloc {
@@ -38,151 +52,140 @@
namespace internal {
-// `LightweightQuarantineEntry` represents one quarantine entry,
-// with the original `Free()` request information.
-struct LightweightQuarantineEntry {
- LightweightQuarantineEntry() = default;
- explicit LightweightQuarantineEntry(void* object) : object(object) {}
- PA_ALWAYS_INLINE void* GetObject() const { return object; }
+template <size_t QuarantineCapacityCount>
+class LightweightQuarantineBranch;
- void* object = nullptr;
-};
-
-template <typename QuarantineEntry, size_t CapacityCount>
-class LightweightQuarantineList {
+class LightweightQuarantineRoot {
public:
- // `CapacityCount` must be power of two.
- static constexpr uint32_t kCapacityCount = CapacityCount;
- static_assert(base::bits::IsPowerOfTwo(kCapacityCount));
-
- // "Entry" is an object that holds free-time information, created for each
- // quarantined object.
- // An application may overwrite `QuarantineEntry` with their custom entry
- // to record more `Free()`-time information.
- using Entry = QuarantineEntry;
- // To be accessed from a crash handler, it must be a trivially copyable.
- static_assert(std::is_trivially_copyable_v<Entry>);
-
- // Entry ids are concatenation of "slot index" and "counter".
- // Their lower bits store "slot index", an index of `slots_`.
- // Their upper bits store "counter", which is incremented every time
- // when used (may overflow). It is used to verify the slot is occupied by that
- // entry.
- static constexpr uint32_t kSlotIndexMask = kCapacityCount - 1;
- static constexpr uint32_t kInvalidEntryID =
- std::numeric_limits<uint32_t>::max();
-
- // "Slot" is a place to put an entry. Each slot owns at most one entry.
- struct Slot {
- void* GetObject() const {
- // We assume `Entry` has `GetObject()` member function.
- return entry.GetObject();
- }
-
- // Used to make sure the metadata entry isn't stale.
- uint32_t entry_id = kInvalidEntryID;
- Entry entry;
- };
- static_assert(std::is_trivially_copyable_v<Slot>);
-
- explicit LightweightQuarantineList(PartitionRoot* root,
+ explicit LightweightQuarantineRoot(PartitionRoot& allocator_root,
size_t capacity_in_bytes = 0)
- : root_(root), capacity_in_bytes_(capacity_in_bytes) {
- PA_CHECK(root);
- // Initialize entry ids with iota.
- // They can be initialized with any value as long as
- // `entry_ids_[i] & kSlotIndexMask` are unique.
- std::iota(entry_ids_.begin(), entry_ids_.end(), 0);
- }
- LightweightQuarantineList(const LightweightQuarantineList&) = delete;
- ~LightweightQuarantineList() { Purge(); }
+ : allocator_root_(allocator_root),
+ capacity_in_bytes_(capacity_in_bytes) {}
- // Quarantines an object. This list holds information you put into `Entry`
- // as much as possible.
- // If the object is too large, this may return `kInvalidEntryID`, meaning
- // that quarantine request has failed (and freed immediately).
- // Otherwise, returns an entry id for the quarantine.
- uint32_t Quarantine(Entry&& entry);
-
- void AccumulateStats(LightweightQuarantineStats& stats) const;
-
- // Determines this list contains an entry with `entry.GetObject() == ptr`.
- bool IsQuarantinedForTesting(void* object);
-
- // Dequarantine all entries.
- void Purge();
-
- // Returns a pointer to an array of `Slot`.
- // Don't try to dereference to avoid harmful races.
- // You can save this address and entry id returned by `Quarantine()`
- // somewhere, and use `GetEntryByID()` to obtain the free time information.
- // E.g. embed an entry id into zapping pattern and detect the pattern in
- // a crash handler to report the free time information.
- uintptr_t GetSlotsAddress() {
- ScopedGuard guard(lock_);
- return reinterpret_cast<uintptr_t>(slots_.data());
+ template <size_t QuarantineCapacityCount>
+ LightweightQuarantineBranch<QuarantineCapacityCount> CreateBranch() {
+ return LightweightQuarantineBranch<QuarantineCapacityCount>(*this);
}
- // Returns an `Entry` associated with the id.
- // May return `nullptr` if it is overwritten by another entry. This can rarely
- // return wrong entry if the id is colliding with another entry.
- // Not thread-safe, use only in crash handling or in tests.
- static const Entry* GetEntryByID(uintptr_t slots_address, uint32_t entry_id) {
- const auto* slots = reinterpret_cast<Slot*>(slots_address);
- const auto& slot = slots[entry_id & kSlotIndexMask];
- if (slot.entry_id != entry_id) {
- return nullptr;
- }
- return &slot.entry;
+ void AccumulateStats(LightweightQuarantineStats& stats) const {
+ stats.count += count_.load(std::memory_order_relaxed);
+ stats.size_in_bytes += size_in_bytes_.load(std::memory_order_relaxed);
+ stats.cumulative_count += cumulative_count_.load(std::memory_order_relaxed);
+ stats.cumulative_size_in_bytes +=
+ cumulative_size_in_bytes_.load(std::memory_order_relaxed);
+ stats.quarantine_miss_count +=
+ quarantine_miss_count_.load(std::memory_order_relaxed);
}
size_t GetCapacityInBytes() const {
return capacity_in_bytes_.load(std::memory_order_relaxed);
}
- void SetCapacityInBytesForTesting(size_t capacity_in_bytes) {
- capacity_in_bytes_.store(capacity_in_bytes, std::memory_order_relaxed);
- // Purge to maintain invariant.
- Purge();
+ void SetCapacityInBytesForTesting(size_t capacity) {
+ capacity_in_bytes_.store(capacity, std::memory_order_relaxed);
+ // `size_in_bytes` may exceed `capacity_in_bytes` here.
+ // Each branch will try to shrink their quarantine later.
}
private:
- Lock lock_;
- // Not `PA_GUARDED_BY` as they have another lock.
- PartitionRoot* const root_;
+ PartitionRoot& allocator_root_;
std::atomic_size_t capacity_in_bytes_;
+ // Number of quarantined entries.
+ std::atomic_size_t count_ = 0;
+ // Total size of quarantined entries, capped by `capacity_in_bytes`.
+ std::atomic_size_t size_in_bytes_ = 0;
+
+ // Stats.
+ std::atomic_size_t cumulative_count_ = 0;
+ std::atomic_size_t cumulative_size_in_bytes_ = 0;
+ std::atomic_size_t quarantine_miss_count_ = 0;
+
+ template <size_t>
+ friend class LightweightQuarantineBranch;
+};
+
+template <size_t QuarantineCapacityCount>
+class LightweightQuarantineBranch {
+ public:
+ // `QuarantineCapacityCount` must be a positive number.
+ static constexpr uint32_t kQuarantineCapacityCount = QuarantineCapacityCount;
+ static_assert(0 < QuarantineCapacityCount);
+
+ using Root = LightweightQuarantineRoot;
+
+ LightweightQuarantineBranch(const LightweightQuarantineBranch&) = delete;
+ LightweightQuarantineBranch(LightweightQuarantineBranch&& b)
+ : root_(b.root_),
+ slots_(std::move(b.slots_)),
+ branch_count_(b.branch_count_),
+ branch_size_in_bytes_(b.branch_size_in_bytes_) {}
+ ~LightweightQuarantineBranch() { Purge(); }
+
+ // Quarantines an object. This list holds information you put into `entry`
+ // as much as possible. If the object is too large, this may return
+ // `false`, meaning that quarantine request has failed (and freed
+ // immediately). Otherwise, returns `true`.
+ bool Quarantine(void* object);
+
+ // Dequarantine all entries **held by this branch**.
+ // It is possible that another branch with entries and it remains untouched.
+ void Purge() {
+ ScopedGuard guard(lock_);
+ PurgeInternal(0, 0);
+ }
+
+ // Determines this list contains an object.
+ bool IsQuarantinedForTesting(void* object) {
+ ScopedGuard guard(lock_);
+ for (size_t i = 0; i < branch_count_; i++) {
+ if (slots_[i] == object) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Root& GetRoot() { return root_; }
+
+ private:
+ explicit LightweightQuarantineBranch(Root& root) : root_(root) {}
+
+ // Try to dequarantine entries to satisfy below:
+ // branch_count_ <= target_branch_count
+ // && root_.size_in_bytes_ <= target_size_in_bytes
+ // It is possible that this branch cannot satisfy the
+ // request as it has control over only what it has. If you need to ensure the
+ // constraint, call `Purge()` for each branch in sequence, synchronously.
+ void PurgeInternal(size_t target_branch_count, size_t target_size_in_bytes)
+ PA_EXCLUSIVE_LOCKS_REQUIRED(lock_);
+
+ Lock lock_;
+ Root& root_;
+
// Non-cryptographic random number generator.
// Thread-unsafe so guarded by `lock_`.
base::InsecureRandomGenerator random_ PA_GUARDED_BY(lock_);
// `slots_` hold an array of quarantined entries.
// The contents of empty slots are undefined and reads should not occur.
- // There is no guarantee that non-empty slots will be placed consecutively.
- std::array<Slot, kCapacityCount> slots_ PA_GUARDED_BY(lock_);
+ // First `branch_count_` slots are used and entries should be shuffled.
+ std::array<void*, kQuarantineCapacityCount> slots_ PA_GUARDED_BY(lock_);
- // Number of quarantined entries, capped by `kCapacityCount`.
- std::atomic_size_t count_ = 0;
- // Total size of quarantined entries, capped by `capacity_in_bytes_`.
- std::atomic_size_t size_in_bytes_ = 0;
- // `entry_ids_` is a supplementary data store to access slots quickly.
- // Its first `count_` elements represents quarantined entry ids and
- // used to choose an entry to dequarantine quickly.
- // The other elements reperent empty slot indices to find an empty slot to
- // fill in quickly. All elements are also responsible for managing upper bits
- // of entry ids so that they are as unique as possible.
- std::array<uint32_t, kCapacityCount> entry_ids_ PA_GUARDED_BY(lock_);
+ // # of quarantined entries in this branch.
+ size_t branch_count_ PA_GUARDED_BY(lock_) = 0;
+ size_t branch_size_in_bytes_ PA_GUARDED_BY(lock_) = 0;
- // Stats.
- std::atomic_size_t cumulative_count_ = 0;
- std::atomic_size_t cumulative_size_in_bytes_ = 0;
- std::atomic_size_t quarantine_miss_count_ = 0;
+ friend class LightweightQuarantineRoot;
};
-using SchedulerLoopQuarantine =
- LightweightQuarantineList<LightweightQuarantineEntry, 1024>;
-extern template class PA_EXPORT_TEMPLATE_DECLARE(
- PA_COMPONENT_EXPORT(PARTITION_ALLOC))
- LightweightQuarantineList<LightweightQuarantineEntry, 1024>;
+#define EXPORT_TEMPLATE \
+ extern template class PA_EXPORT_TEMPLATE_DECLARE( \
+ PA_COMPONENT_EXPORT(PARTITION_ALLOC))
+using LightweightQuarantineBranchForTesting = LightweightQuarantineBranch<1024>;
+using SchedulerLoopQuarantineRoot = LightweightQuarantineRoot;
+using SchedulerLoopQuarantineBranch = LightweightQuarantineBranch<1024>;
+EXPORT_TEMPLATE LightweightQuarantineBranch<1024>;
+#undef EXPORT_TEMPLATE
} // namespace internal
diff --git a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine_unittest.cc
index c60b834..dc83b3a 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/lightweight_quarantine_unittest.cc
@@ -21,16 +21,15 @@
return entry_slot_span->GetUtilizedSlotSize();
}
+using QuarantineRoot = internal::LightweightQuarantineRoot;
+using QuarantineBranch = internal::LightweightQuarantineBranchForTesting;
+
struct LightweightQuarantineTestParam {
size_t capacity_in_bytes;
};
-
-using QuarantineList =
- internal::LightweightQuarantineList<internal::LightweightQuarantineEntry,
- 1024>;
-constexpr LightweightQuarantineTestParam kSmallQuarantineList = {
+constexpr LightweightQuarantineTestParam kSmallQuarantineBranch = {
.capacity_in_bytes = 256};
-constexpr LightweightQuarantineTestParam kLargeQuarantineList = {
+constexpr LightweightQuarantineTestParam kLargeQuarantineBranch = {
.capacity_in_bytes = 4096};
class PartitionAllocLightweightQuarantineTest
@@ -41,8 +40,10 @@
allocator_ =
std::make_unique<PartitionAllocatorForTesting>(PartitionOptions{});
- list_ = std::make_unique<QuarantineList>(allocator_->root(),
- param.capacity_in_bytes);
+
+ root_.emplace(*allocator_->root(), param.capacity_in_bytes);
+ branch_.emplace(
+ root_->CreateBranch<QuarantineBranch::kQuarantineCapacityCount>());
auto stats = GetStats();
ASSERT_EQ(0u, stats.size_in_bytes);
@@ -53,50 +54,49 @@
void TearDown() override {
// |Purge()|d here.
- list_ = nullptr;
+ branch_.reset();
+ root_.reset();
allocator_ = nullptr;
}
- PartitionRoot* GetRoot() const { return allocator_->root(); }
+ PartitionRoot* GetPartitionRoot() const { return allocator_->root(); }
- QuarantineList* GetList() const { return list_.get(); }
+ QuarantineRoot* GetQuarantineRoot() { return &root_.value(); }
+ QuarantineBranch* GetQuarantineBranch() { return &branch_.value(); }
LightweightQuarantineStats GetStats() const {
LightweightQuarantineStats stats{};
- list_->AccumulateStats(stats);
+ root_->AccumulateStats(stats);
return stats;
}
std::unique_ptr<PartitionAllocatorForTesting> allocator_;
- std::unique_ptr<QuarantineList> list_;
+ std::optional<QuarantineRoot> root_;
+ std::optional<QuarantineBranch> branch_;
};
INSTANTIATE_TEST_SUITE_P(
PartitionAllocLightweightQuarantineTestMultipleQuarantineSizeInstantiation,
PartitionAllocLightweightQuarantineTest,
- ::testing::Values(kSmallQuarantineList, kLargeQuarantineList));
+ ::testing::Values(kSmallQuarantineBranch, kLargeQuarantineBranch));
} // namespace
TEST_P(PartitionAllocLightweightQuarantineTest, Basic) {
constexpr size_t kObjectSize = 1;
- uintptr_t slots_address = GetList()->GetSlotsAddress();
- const size_t capacity_in_bytes = GetList()->GetCapacityInBytes();
+ const size_t capacity_in_bytes =
+ GetQuarantineBranch()->GetRoot().GetCapacityInBytes();
constexpr size_t kCount = 100;
for (size_t i = 1; i <= kCount; i++) {
- void* object = GetRoot()->Alloc(kObjectSize);
+ void* object = GetPartitionRoot()->Alloc(kObjectSize);
const size_t size = GetObjectSize(object);
const size_t max_count = capacity_in_bytes / size;
- auto entry = QuarantineList::Entry(object);
- const uint32_t entry_id = GetList()->Quarantine(std::move(entry));
- const auto* entry_ptr =
- QuarantineList::GetEntryByID(slots_address, entry_id);
+ const bool success = GetQuarantineBranch()->Quarantine(object);
- ASSERT_NE(entry_ptr, nullptr);
- ASSERT_EQ(object, entry_ptr->GetObject());
- ASSERT_TRUE(GetList()->IsQuarantinedForTesting(object));
+ ASSERT_TRUE(success);
+ ASSERT_TRUE(GetQuarantineBranch()->IsQuarantinedForTesting(object));
const auto expected_count = std::min(i, max_count);
auto stats = GetStats();
@@ -109,16 +109,17 @@
TEST_P(PartitionAllocLightweightQuarantineTest, TooLargeAllocation) {
constexpr size_t kObjectSize = 1 << 26; // 64 MiB.
- const size_t capacity_in_bytes = GetList()->GetCapacityInBytes();
+ const size_t capacity_in_bytes =
+ GetQuarantineBranch()->GetRoot().GetCapacityInBytes();
- void* object = GetRoot()->Alloc(kObjectSize);
+ void* object = GetPartitionRoot()->Alloc(kObjectSize);
const size_t size = GetObjectSize(object);
ASSERT_GT(size, capacity_in_bytes);
- auto entry = QuarantineList::Entry(object);
- GetList()->Quarantine(std::move(entry));
+ const bool success = GetQuarantineBranch()->Quarantine(object);
- ASSERT_FALSE(GetList()->IsQuarantinedForTesting(object));
+ ASSERT_FALSE(success);
+ ASSERT_FALSE(GetQuarantineBranch()->IsQuarantinedForTesting(object));
auto stats = GetStats();
ASSERT_EQ(0u, stats.size_in_bytes);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer_unittest.cc
index 742138c..2f501dd 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/memory_reclaimer_unittest.cc
@@ -44,10 +44,9 @@
// Otherwise, we will see no PartitionAllocator is registered.
MemoryReclaimer::Instance()->ResetForTesting();
- allocator_ =
- std::make_unique<PartitionAllocatorForTesting>(PartitionOptions{
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ PartitionOptions opts;
+ opts.star_scan_quarantine = PartitionOptions::kAllowed;
+ allocator_ = std::make_unique<PartitionAllocatorForTesting>(opts);
allocator_->root()->UncapEmptySlotSpanMemoryForTesting();
PartitionAllocGlobalInit(HandleOOM);
}
diff --git a/base/allocator/partition_allocator/src/partition_alloc/page_allocator.cc b/base/allocator/partition_allocator/src/partition_alloc/page_allocator.cc
index f05060f..5065d5c 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/page_allocator.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/page_allocator.cc
@@ -5,12 +5,12 @@
#include "partition_alloc/page_allocator.h"
#include <atomic>
+#include <bit>
#include <cstdint>
#include "build/build_config.h"
#include "partition_alloc/address_space_randomization.h"
#include "partition_alloc/page_allocator_internal.h"
-#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/thread_annotations.h"
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/partition_lock.h"
@@ -79,7 +79,7 @@
uintptr_t alignment_offset,
PageAccessibilityConfiguration accessibility) {
PA_DCHECK(base_length >= trim_length);
- PA_DCHECK(internal::base::bits::IsPowerOfTwo(alignment));
+ PA_DCHECK(std::has_single_bit(alignment));
PA_DCHECK(alignment_offset < alignment);
uintptr_t new_base =
NextAlignedWithOffset(base_address, alignment, alignment_offset);
@@ -108,7 +108,7 @@
uintptr_t NextAlignedWithOffset(uintptr_t address,
uintptr_t alignment,
uintptr_t requested_offset) {
- PA_DCHECK(internal::base::bits::IsPowerOfTwo(alignment));
+ PA_DCHECK(std::has_single_bit(alignment));
PA_DCHECK(requested_offset < alignment);
uintptr_t actual_offset = address & (alignment - 1);
@@ -183,7 +183,7 @@
PA_DCHECK(!(length & internal::PageAllocationGranularityOffsetMask()));
PA_DCHECK(align >= internal::PageAllocationGranularity());
// Alignment must be power of 2 for masking math to work.
- PA_DCHECK(internal::base::bits::IsPowerOfTwo(align));
+ PA_DCHECK(std::has_single_bit(align));
PA_DCHECK(align_offset < align);
PA_DCHECK(!(align_offset & internal::PageAllocationGranularityOffsetMask()));
PA_DCHECK(!(address & internal::PageAllocationGranularityOffsetMask()));
@@ -287,6 +287,13 @@
internal::SetSystemPagesAccessInternal(address, length, accessibility);
}
+void SetSystemPagesAccess(void* address,
+ size_t length,
+ PageAccessibilityConfiguration accessibility) {
+ SetSystemPagesAccess(reinterpret_cast<uintptr_t>(address), length,
+ accessibility);
+}
+
void DecommitSystemPages(
uintptr_t address,
size_t length,
diff --git a/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc b/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc
index 571c2c0..9d66f0c 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/page_allocator_internals_posix.cc
@@ -10,8 +10,11 @@
// PA_PROT_BTI requests a page that supports BTI landing pads.
#define PA_PROT_BTI 0x10
+
// PA_PROT_MTE requests a page that's suitable for memory tagging.
+#if defined(ARCH_CPU_ARM64)
#define PA_PROT_MTE 0x20
+#endif // defined(ARCH_CPU_ARM64)
namespace partition_alloc::internal {
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.cc
index 6ad0d1f..faeb526 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.cc
@@ -5,6 +5,7 @@
#include "partition_alloc/partition_address_space.h"
#include <array>
+#include <bit>
#include <cstddef>
#include <cstdint>
#include <ostream>
@@ -14,7 +15,6 @@
#include "partition_alloc/address_pool_manager.h"
#include "partition_alloc/compressed_pointer.h"
#include "partition_alloc/page_allocator.h"
-#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_base/debug/alias.h"
#include "partition_alloc/partition_alloc_buildflags.h"
@@ -301,7 +301,7 @@
PA_CHECK(pool_base);
PA_CHECK(size <= kConfigurablePoolMaxSize);
PA_CHECK(size >= kConfigurablePoolMinSize);
- PA_CHECK(base::bits::IsPowerOfTwo(size));
+ PA_CHECK(std::has_single_bit(size));
PA_CHECK(pool_base % size == 0);
setup_.configurable_pool_base_address_ = pool_base;
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h b/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h
index d6a342b..0b115ee 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_address_space.h
@@ -5,13 +5,13 @@
#ifndef BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_PARTITION_ADDRESS_SPACE_H_
#define BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_PARTITION_ADDRESS_SPACE_H_
+#include <bit>
#include <cstddef>
#include <utility>
#include "build/build_config.h"
#include "partition_alloc/address_pool_manager_types.h"
#include "partition_alloc/page_allocator_constants.h"
-#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_base/component_export.h"
#include "partition_alloc/partition_alloc_base/notreached.h"
@@ -270,17 +270,17 @@
// ArrayBuffers be located inside of it.
static constexpr size_t kRegularPoolSize = kPoolMaxSize;
static constexpr size_t kBRPPoolSize = kPoolMaxSize;
- static_assert(base::bits::IsPowerOfTwo(kRegularPoolSize));
- static_assert(base::bits::IsPowerOfTwo(kBRPPoolSize));
+ static_assert(std::has_single_bit(kRegularPoolSize));
+ static_assert(std::has_single_bit(kBRPPoolSize));
#if BUILDFLAG(ENABLE_THREAD_ISOLATION)
static constexpr size_t kThreadIsolatedPoolSize = kGiB / 4;
- static_assert(base::bits::IsPowerOfTwo(kThreadIsolatedPoolSize));
+ static_assert(std::has_single_bit(kThreadIsolatedPoolSize));
#endif
static constexpr size_t kConfigurablePoolMaxSize = kPoolMaxSize;
static constexpr size_t kConfigurablePoolMinSize = 1 * kGiB;
static_assert(kConfigurablePoolMinSize <= kConfigurablePoolMaxSize);
- static_assert(base::bits::IsPowerOfTwo(kConfigurablePoolMaxSize));
- static_assert(base::bits::IsPowerOfTwo(kConfigurablePoolMinSize));
+ static_assert(std::has_single_bit(kConfigurablePoolMaxSize));
+ static_assert(std::has_single_bit(kConfigurablePoolMinSize));
#if BUILDFLAG(IS_IOS)
@@ -295,8 +295,8 @@
static constexpr size_t kBRPPoolSizeForIOSTestProcess = kGiB / 4;
static_assert(kRegularPoolSizeForIOSTestProcess < kRegularPoolSize);
static_assert(kBRPPoolSizeForIOSTestProcess < kBRPPoolSize);
- static_assert(base::bits::IsPowerOfTwo(kRegularPoolSizeForIOSTestProcess));
- static_assert(base::bits::IsPowerOfTwo(kBRPPoolSizeForIOSTestProcess));
+ static_assert(std::has_single_bit(kRegularPoolSizeForIOSTestProcess));
+ static_assert(std::has_single_bit(kBRPPoolSizeForIOSTestProcess));
#endif // BUILDFLAG(IOS_IOS)
#if !PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE)
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.h
index 6b632d6..8288058 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/apple/mach_logging.h
@@ -54,7 +54,7 @@
#endif
#define PA_MACH_LOG_STREAM(severity, mach_err) \
- PA_COMPACT_GOOGLE_LOG_EX_##severity(MachLogMessage, mach_err).stream()
+ PA_COMPACT_GOOGLE_PLOG_EX_##severity(MachLogMessage, mach_err).stream()
#define PA_MACH_VLOG_STREAM(verbose_level, mach_err) \
::partition_alloc::internal::logging::MachLogMessage( \
__FILE__, __LINE__, -verbose_level, mach_err) \
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits.h
index 93b8784..0693646 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits.h
@@ -27,24 +27,11 @@
!std::same_as<T, char16_t> && !std::same_as<T, char32_t> &&
!std::same_as<T, wchar_t>;
-// Returns true iff |value| is a power of 2.
-//
-// TODO(https://crbug.com/1414634): Replace with std::has_single_bit().
-template <UnsignedInteger T>
-constexpr bool IsPowerOfTwo(T value) {
- // From "Hacker's Delight": Section 2.1 Manipulating Rightmost Bits.
- //
- // Only positive integers with a single bit set are powers of two. If only one
- // bit is set in x (e.g. 0b00000100000000) then |x-1| will have that bit set
- // to zero and all bits to its right set to 1 (e.g. 0b00000011111111). Hence
- // |x & (x-1)| is 0 iff x is a power of two.
- return value > 0 && (value & (value - 1)) == 0;
-}
-
// Round down |size| to a multiple of alignment, which must be a power of two.
-template <UnsignedInteger T>
+template <typename T>
+ requires UnsignedInteger<T>
inline constexpr T AlignDown(T size, T alignment) {
- PA_BASE_DCHECK(IsPowerOfTwo(alignment));
+ PA_BASE_DCHECK(std::has_single_bit(alignment));
return size & ~(alignment - 1);
}
@@ -58,9 +45,10 @@
}
// Round up |size| to a multiple of alignment, which must be a power of two.
-template <UnsignedInteger T>
+template <typename T>
+ requires UnsignedInteger<T>
inline constexpr T AlignUp(T size, T alignment) {
- PA_BASE_DCHECK(IsPowerOfTwo(alignment));
+ PA_BASE_DCHECK(std::has_single_bit(alignment));
return (size + alignment - 1) & ~(alignment - 1);
}
@@ -78,9 +66,8 @@
// A common use for this function is to measure the number of bits required to
// contain a value; for that case use std::bit_width().
//
-// A common use for this function is to shift a bit by its result; instead of
-// doing so, use std::bit_floor(). TODO(https://crbug.com/1414634): Replace
-// existing uses that do that.
+// A common use for this function is to take its result and use it to left-shift
+// a bit; instead of doing so, use std::bit_floor().
constexpr int Log2Floor(uint32_t n) {
return 31 - std::countl_zero(n);
}
@@ -90,9 +77,8 @@
// A common use for this function is to measure the number of bits required to
// contain a value; for that case use std::bit_width().
//
-// A common use for this function is to shift a bit by its result; instead of
-// doing so, use std::bit_ceil(). TODO(https://crbug.com/1414634): Replace
-// existing uses that do that.
+// A common use for this function is to take its result and use it to left-shift
+// a bit; instead of doing so, use std::bit_ceil().
constexpr int Log2Ceiling(uint32_t n) {
// When n == 0, we want the function to return -1.
// When n == 0, (n - 1) will underflow to 0xFFFFFFFF, which is
@@ -103,7 +89,8 @@
// Returns a value of type T with a single bit set in the left-most position.
// Can be used instead of manually shifting a 1 to the left. Unlike the other
// functions in this file, usable for any integral type.
-template <std::integral T>
+template <typename T>
+ requires std::integral<T>
constexpr T LeftmostBit() {
T one(1u);
return one << (8 * sizeof(T) - 1);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits_pa_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits_pa_unittest.cc
index c6ff097..532db59 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits_pa_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/bits_pa_unittest.cc
@@ -117,19 +117,6 @@
AlignDown(reinterpret_cast<uint8_t*>(1), kUintPtrTMax / 2 + 1));
}
-TEST(BitsTestPA, PowerOfTwo) {
- EXPECT_FALSE(IsPowerOfTwo(0u));
- EXPECT_TRUE(IsPowerOfTwo(1u));
- EXPECT_TRUE(IsPowerOfTwo(2u));
- // Unsigned 64 bit cases.
- for (uint32_t i = 2; i < 64; i++) {
- const uint64_t val = uint64_t{1} << i;
- EXPECT_FALSE(IsPowerOfTwo(val - 1));
- EXPECT_TRUE(IsPowerOfTwo(val));
- EXPECT_FALSE(IsPowerOfTwo(val + 1));
- }
-}
-
TEST(BitsTestPA, LeftMostBit) {
// Construction of a signed type from an unsigned one of the same width
// preserves all bits. Explicitly confirming this behavior here to illustrate
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.cc
index b24b893..9a0e689 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/cpu.cc
@@ -23,11 +23,17 @@
// Temporary definitions until a new hwcap.h is pulled in everywhere.
// https://crbug.com/1265965
+#if defined(ARCH_CPU_ARM64)
#ifndef HWCAP2_MTE
#define HWCAP2_MTE (1 << 18)
+#endif
+#ifndef HWCAP2_BTI
#define HWCAP2_BTI (1 << 17)
#endif
-#endif
+#endif // # defined(ARCH_CPU_ARM64)
+
+#endif // defined(ARCH_CPU_ARM_FAMILY) && (BUILDFLAG(IS_ANDROID) ||
+ // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
#if defined(ARCH_CPU_X86_FAMILY)
#if defined(COMPILER_MSVC)
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.h
index 24c1deb..5fcfb4a 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace.h
@@ -71,4 +71,4 @@
} // namespace partition_alloc::internal::base::debug
-#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_SRC_PARTITION_ALLOC_BASE_DEBUG_STACK_TRACE_H_
+#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_PARTITION_ALLOC_BASE_DEBUG_STACK_TRACE_H_
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.cc
index 3fed895..98966ad 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/debug/stack_trace_posix.cc
@@ -17,7 +17,6 @@
#endif
#if BUILDFLAG(IS_APPLE)
-#define HAVE_DLADDR
#include <dlfcn.h>
#endif
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.cc
index d4fd55d..ba89c45 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.cc
@@ -25,10 +25,6 @@
#include <io.h>
#include <windows.h>
-// Windows warns on using write(). It prefers _write().
-#define write(fd, buf, count) _write(fd, buf, static_cast<unsigned int>(count))
-// Windows doesn't define STDERR_FILENO. Define it here.
-#define STDERR_FILENO 2
#endif
@@ -117,7 +113,4 @@
}
}
-// This was defined at the beginning of this file.
-#undef write
-
} // namespace partition_alloc::internal::logging
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.h
index 6c28fe2..47b0793 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/logging.h
@@ -154,30 +154,51 @@
// A few definitions of macros that don't generate much code. These are used
// by PA_LOG() and LOG_IF, etc. Since these are used all over our code, it's
// better to have compact code for these operations.
-#define PA_COMPACT_GOOGLE_LOG_EX_INFO(ClassName, ...) \
+#define PA_COMPACT_GOOGLE_LOG_EX_INFO(ClassName) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_INFO)
+#define PA_COMPACT_GOOGLE_PLOG_EX_INFO(ClassName, error_code) \
::partition_alloc::internal::logging::ClassName( \
__FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_INFO, \
- ##__VA_ARGS__)
-#define PA_COMPACT_GOOGLE_LOG_EX_WARNING(ClassName, ...) \
- ::partition_alloc::internal::logging::ClassName( \
- __FILE__, __LINE__, \
- ::partition_alloc::internal::logging::LOGGING_WARNING, ##__VA_ARGS__)
-#define PA_COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ...) \
+ error_code)
+#define PA_COMPACT_GOOGLE_LOG_EX_WARNING(ClassName) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, \
+ ::partition_alloc::internal::logging::LOGGING_WARNING)
+#define PA_COMPACT_GOOGLE_PLOG_EX_WARNING(ClassName, error_code) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, \
+ ::partition_alloc::internal::logging::LOGGING_WARNING)
+#define PA_COMPACT_GOOGLE_LOG_EX_ERROR(ClassName) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_ERROR)
+#define PA_COMPACT_GOOGLE_PLOG_EX_ERROR(ClassName, error_code) \
::partition_alloc::internal::logging::ClassName( \
__FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_ERROR, \
- ##__VA_ARGS__)
-#define PA_COMPACT_GOOGLE_LOG_EX_FATAL(ClassName, ...) \
+ error_code)
+#define PA_COMPACT_GOOGLE_LOG_EX_FATAL(ClassName) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_FATAL)
+#define PA_COMPACT_GOOGLE_PLOG_EX_FATAL(ClassName, error_code) \
::partition_alloc::internal::logging::ClassName( \
__FILE__, __LINE__, ::partition_alloc::internal::logging::LOGGING_FATAL, \
- ##__VA_ARGS__)
-#define PA_COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName, ...) \
- ::partition_alloc::internal::logging::ClassName( \
- __FILE__, __LINE__, \
- ::partition_alloc::internal::logging::LOGGING_DFATAL, ##__VA_ARGS__)
-#define PA_COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName, ...) \
- ::partition_alloc::internal::logging::ClassName( \
- __FILE__, __LINE__, \
- ::partition_alloc::internal::logging::LOGGING_DCHECK, ##__VA_ARGS__)
+ error_code)
+#define PA_COMPACT_GOOGLE_LOG_EX_DFATAL(ClassName) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, \
+ ::partition_alloc::internal::logging::LOGGING_DFATAL)
+#define PA_COMPACT_GOOGLE_PLOG_EX_DFATAL(ClassName, error_code) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, \
+ ::partition_alloc::internal::logging::LOGGING_DFATAL, error_code)
+#define PA_COMPACT_GOOGLE_LOG_EX_DCHECK(ClassName) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, \
+ ::partition_alloc::internal::logging::LOGGING_DCHECK)
+#define PA_COMPACT_GOOGLE_PLOG_EX_DCHECK(ClassName, error_code) \
+ ::partition_alloc::internal::logging::ClassName( \
+ __FILE__, __LINE__, \
+ ::partition_alloc::internal::logging::LOGGING_DCHECK, error_code)
#define PA_COMPACT_GOOGLE_LOG_INFO PA_COMPACT_GOOGLE_LOG_EX_INFO(LogMessage)
#define PA_COMPACT_GOOGLE_LOG_WARNING \
@@ -194,8 +215,8 @@
// as PA_COMPACT_GOOGLE_LOG_ERROR, and also define ERROR the same way that
// the Windows SDK does for consistency.
#define PA_ERROR 0
-#define PA_COMPACT_GOOGLE_LOG_EX_0(ClassName, ...) \
- PA_COMPACT_GOOGLE_LOG_EX_ERROR(ClassName, ##__VA_ARGS__)
+#define PA_COMPACT_GOOGLE_LOG_EX_0(ClassName) \
+ PA_COMPACT_GOOGLE_LOG_EX_ERROR(ClassName)
#define PA_COMPACT_GOOGLE_LOG_0 PA_COMPACT_GOOGLE_LOG_ERROR
// Needed for LOG_IS_ON(ERROR).
constexpr LogSeverity LOGGING_0 = LOGGING_ERROR;
@@ -279,13 +300,13 @@
#if BUILDFLAG(IS_WIN)
#define PA_PLOG_STREAM(severity) \
- PA_COMPACT_GOOGLE_LOG_EX_##severity( \
+ PA_COMPACT_GOOGLE_PLOG_EX_##severity( \
Win32ErrorLogMessage, \
::partition_alloc::internal::logging::GetLastSystemErrorCode()) \
.stream()
#elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
#define PA_PLOG_STREAM(severity) \
- PA_COMPACT_GOOGLE_LOG_EX_##severity( \
+ PA_COMPACT_GOOGLE_PLOG_EX_##severity( \
ErrnoLogMessage, \
::partition_alloc::internal::logging::GetLastSystemErrorCode()) \
.stream()
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.h
index fa695be..330cb65 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/rand_util.h
@@ -15,8 +15,8 @@
class RandomGenerator;
namespace internal {
-template <typename QuarantineEntry, size_t CountCapacity>
-class LightweightQuarantineList;
+template <size_t>
+class LightweightQuarantineBranch;
}
} // namespace partition_alloc
@@ -89,8 +89,8 @@
// need a secure PRNG, as it's used for ASLR and zeroing some allocations at
// free() time.
friend class ::partition_alloc::RandomGenerator;
- template <typename QuarantineEntry, size_t CountCapacity>
- friend class ::partition_alloc::internal::LightweightQuarantineList;
+ template <size_t>
+ friend class ::partition_alloc::internal::LightweightQuarantineBranch;
};
} // namespace partition_alloc::internal::base
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.h
index 2d62f65..ee014e6 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/strings/safe_sprintf.h
@@ -204,12 +204,14 @@
template <class T>
Arg(T* p) : ptr((void*)p), type(POINTER) {}
+ struct Integer {
+ int64_t i;
+ unsigned char width;
+ };
+
union {
// An integer-like value.
- struct {
- int64_t i;
- unsigned char width;
- } integer;
+ Integer integer;
// A C-style text string.
const char* str;
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h
index e5d8f93..ef7ac32 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_base/threading/platform_thread_for_testing.h
@@ -70,4 +70,4 @@
} // namespace partition_alloc::internal::base
-#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_PARTITION_ALLOC_BASE_THREADING_PLATFORM_THREADD_FOR_TESTING_H_
+#endif // BASE_ALLOCATOR_PARTITION_ALLOCATOR_SRC_PARTITION_ALLOC_PARTITION_ALLOC_BASE_THREADING_PLATFORM_THREAD_FOR_TESTING_H_
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h
index 1788a7f..9ac738d 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_check.h
@@ -44,7 +44,8 @@
int error = errno; \
::partition_alloc::internal::base::debug::Alias(&error); \
PA_IMMEDIATE_CRASH(); \
- }
+ } \
+ static_assert(true)
#if BUILDFLAG(PA_DCHECK_IS_ON)
#define PA_DPCHECK(condition) PA_PCHECK(condition)
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc
index f4918f3..e4f7791 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_perftest.cc
@@ -136,11 +136,13 @@
}
private:
- static constexpr partition_alloc::PartitionOptions kOpts = {
+ static constexpr partition_alloc::PartitionOptions kOpts = []() {
+ partition_alloc::PartitionOptions opts;
#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
- .thread_cache = PartitionOptions::kEnabled,
+ opts.thread_cache = PartitionOptions::kEnabled;
#endif
- };
+ return opts;
+ }();
PartitionAllocatorForTesting<internal::DisallowLeaks> allocator_{kOpts};
internal::ThreadCacheProcessScopeForTesting scope_;
};
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc
index ce78d35..f4c5fb3 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_alloc_unittest.cc
@@ -5,6 +5,7 @@
#include "partition_alloc/partition_alloc_for_testing.h"
#include <algorithm>
+#include <bit>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
@@ -354,6 +355,13 @@
return root;
}
+ PartitionOptions GetCommonPartitionOptions() {
+ PartitionOptions opts;
+ opts.ref_count_size = GetParam().ref_count_size;
+ opts.zapping_by_free_flags = PartitionOptions::kEnabled;
+ return opts;
+ }
+
void InitializeMainTestAllocators() {
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
PartitionOptions::EnableToggle enable_backup_ref_ptr =
@@ -364,16 +372,15 @@
if (pkey != -1) {
pkey_ = pkey;
}
+
+ PartitionOptions pkey_opts = GetCommonPartitionOptions();
+ pkey_opts.aligned_alloc = PartitionOptions::kAllowed;
+ pkey_opts.thread_isolation = ThreadIsolationOption(pkey_);
// We always want to have a pkey allocator initialized to make sure that the
// other pools still work. As part of the initializition, we tag some memory
// with the new pkey, effectively making it read-only. So there's some
// potential for breakage that this should catch.
- InitializeTestRoot(pkey_allocator.root(),
- PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- .ref_count_size = GetParam().ref_count_size,
- .thread_isolation = ThreadIsolationOption(pkey_),
- },
+ InitializeTestRoot(pkey_allocator.root(), pkey_opts,
PartitionTestOptions{.use_memory_reclaimer = true});
ThreadIsolationOption thread_isolation_opt;
@@ -386,43 +393,40 @@
#endif
}
#endif // BUILDFLAG(ENABLE_PKEYS)
- InitializeTestRoot(
- allocator.root(),
- PartitionOptions {
+
+ PartitionOptions opts = GetCommonPartitionOptions();
#if !BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT) || \
BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT)
- // AlignedAlloc() can't be called when BRP is in the
- // "before allocation" mode, because this mode adds extras before
- // the allocation. Extras after the allocation are ok.
- .aligned_alloc = PartitionOptions::kAllowed,
+ // AlignedAlloc() can't be called when BRP is in the
+ // "before allocation" mode, because this mode adds extras before
+ // the allocation. Extras after the allocation are ok.
+ opts.aligned_alloc = PartitionOptions::kAllowed;
#endif
#if BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
- .backup_ref_ptr = enable_backup_ref_ptr,
+ opts.backup_ref_ptr = enable_backup_ref_ptr;
#endif
- .ref_count_size = GetParam().ref_count_size,
#if BUILDFLAG(ENABLE_PKEYS)
- .thread_isolation = thread_isolation_opt,
+ opts.thread_isolation = thread_isolation_opt;
#endif
#if PA_CONFIG(HAS_MEMORY_TAGGING)
- .memory_tagging = {
- .enabled =
- partition_alloc::internal::base::CPU::GetInstanceNoAllocation()
- .has_mte()
- ? PartitionOptions::kEnabled
- : PartitionOptions::kDisabled,
- }
+ opts.memory_tagging = {
+ .enabled =
+ partition_alloc::internal::base::CPU::GetInstanceNoAllocation()
+ .has_mte()
+ ? PartitionOptions::kEnabled
+ : PartitionOptions::kDisabled,
+ };
#endif // PA_CONFIG(HAS_MEMORY_TAGGING)
- },
+ InitializeTestRoot(
+ allocator.root(), opts,
PartitionTestOptions{.use_memory_reclaimer = true,
.uncap_empty_slot_span_memory = true,
.set_bucket_distribution = true});
+ PartitionOptions aligned_opts = GetCommonPartitionOptions();
+ aligned_opts.aligned_alloc = PartitionOptions::kAllowed;
InitializeTestRoot(
- aligned_allocator.root(),
- PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- .ref_count_size = GetParam().ref_count_size,
- },
+ aligned_allocator.root(), aligned_opts,
PartitionTestOptions{.use_memory_reclaimer = true,
.uncap_empty_slot_span_memory = true,
.set_bucket_distribution = true});
@@ -3621,12 +3625,12 @@
}
TEST_P(PartitionAllocTest, SchedulerLoopQuarantine) {
- SchedulerLoopQuarantine& list =
- allocator.root()->GetSchedulerLoopQuarantineForTesting();
+ SchedulerLoopQuarantineBranch& branch =
+ allocator.root()->GetSchedulerLoopQuarantineBranchForTesting();
constexpr size_t kCapacityInBytes = std::numeric_limits<size_t>::max();
- size_t original_capacity_in_bytes = list.GetCapacityInBytes();
- list.SetCapacityInBytesForTesting(kCapacityInBytes);
+ size_t original_capacity_in_bytes = branch.GetRoot().GetCapacityInBytes();
+ branch.GetRoot().SetCapacityInBytesForTesting(kCapacityInBytes);
for (size_t size : kTestSizes) {
SCOPED_TRACE(size);
@@ -3634,7 +3638,7 @@
void* object = allocator.root()->Alloc(size);
allocator.root()->Free<FreeFlags::kSchedulerLoopQuarantine>(object);
- ASSERT_TRUE(list.IsQuarantinedForTesting(object));
+ ASSERT_TRUE(branch.IsQuarantinedForTesting(object));
}
for (int i = 0; i < 10; ++i) {
@@ -3643,8 +3647,8 @@
allocator.root(), 250);
}
- list.Purge();
- list.SetCapacityInBytesForTesting(original_capacity_in_bytes);
+ branch.Purge();
+ branch.GetRoot().SetCapacityInBytesForTesting(original_capacity_in_bytes);
}
TEST_P(PartitionAllocTest, ZapOnFree) {
@@ -4922,9 +4926,7 @@
allocator.root()->PurgeMemory(PurgeFlags::kDecommitEmptySlotSpans |
PurgeFlags::kDiscardUnusedSystemPages);
std::unique_ptr<PartitionRoot> new_root = CreateCustomTestRoot(
- PartitionOptions{
- .ref_count_size = GetParam().ref_count_size,
- },
+ GetCommonPartitionOptions(),
PartitionTestOptions{.set_bucket_distribution = true});
// Realloc from |allocator.root()| into |new_root|.
@@ -5111,7 +5113,7 @@
const size_t min_pool_size = PartitionAddressSpace::ConfigurablePoolMinSize();
for (size_t pool_size = max_pool_size; pool_size >= min_pool_size;
pool_size /= 2) {
- PA_DCHECK(partition_alloc::internal::base::bits::IsPowerOfTwo(pool_size));
+ PA_DCHECK(std::has_single_bit(pool_size));
EXPECT_FALSE(IsConfigurablePoolAvailable());
uintptr_t pool_base =
AllocPages(pool_size, pool_size,
@@ -5123,13 +5125,11 @@
EXPECT_TRUE(IsConfigurablePoolAvailable());
+ PartitionOptions opts = GetCommonPartitionOptions();
+ opts.use_configurable_pool = PartitionOptions::kAllowed;
std::unique_ptr<PartitionRoot> root = CreateCustomTestRoot(
- PartitionOptions{
- .use_configurable_pool = PartitionOptions::kAllowed,
- .ref_count_size = GetParam().ref_count_size,
- },
- PartitionTestOptions{.uncap_empty_slot_span_memory = true,
- .set_bucket_distribution = true});
+ opts, PartitionTestOptions{.uncap_empty_slot_span_memory = true,
+ .set_bucket_distribution = true});
const size_t count = 250;
std::vector<void*> allocations(count, nullptr);
@@ -5157,9 +5157,7 @@
// Use another root, since the ones from the test harness disable the empty
// slot span size cap.
std::unique_ptr<PartitionRoot> root = CreateCustomTestRoot(
- PartitionOptions{
- .ref_count_size = GetParam().ref_count_size,
- },
+ GetCommonPartitionOptions(),
PartitionTestOptions{.set_bucket_distribution = true});
// Allocate some memory, don't free it to keep committed memory.
@@ -5212,9 +5210,7 @@
TEST_P(PartitionAllocTest, IncreaseEmptySlotSpanRingSize) {
std::unique_ptr<PartitionRoot> root = CreateCustomTestRoot(
- PartitionOptions{
- .ref_count_size = GetParam().ref_count_size,
- },
+ GetCommonPartitionOptions(),
PartitionTestOptions{.uncap_empty_slot_span_memory = true,
.set_bucket_distribution = true});
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.cc
index bec02a0..b66deb5 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.cc
@@ -5,6 +5,7 @@
#include "partition_alloc/partition_bucket.h"
#include <algorithm>
+#include <bit>
#include <cstdint>
#include <tuple>
@@ -192,7 +193,7 @@
size_t raw_size,
size_t slot_span_alignment) {
PA_DCHECK((slot_span_alignment >= PartitionPageSize()) &&
- base::bits::IsPowerOfTwo(slot_span_alignment));
+ std::has_single_bit(slot_span_alignment));
// No static EXCLUSIVE_LOCKS_REQUIRED(), as the checker doesn't understand
// scoped unlocking.
@@ -414,7 +415,7 @@
//
// Direct map never uses tagging, as size is always >kMaxMemoryTaggingSize.
PA_DCHECK(raw_size > kMaxMemoryTaggingSize);
- const bool ok = root->TryRecommitSystemPagesForData(
+ const bool ok = root->TryRecommitSystemPagesForDataWithAcquiringLock(
slot_start, slot_size, PageAccessibilityDisposition::kRequireUpdate,
false);
if (!ok) {
@@ -910,6 +911,7 @@
PA_ALWAYS_INLINE uintptr_t
PartitionBucket::ProvisionMoreSlotsAndAllocOne(PartitionRoot* root,
+ AllocFlags flags,
SlotSpanMetadata* slot_span) {
PA_DCHECK(slot_span != SlotSpanMetadata::get_sentinel_slot_span());
size_t num_slots = slot_span->num_unprovisioned_slots;
@@ -938,6 +940,25 @@
// rounded up.
PA_DCHECK(commit_end > commit_start);
+ // If lazy commit is enabled, meaning system pages in the slot span come
+ // in an initially decommitted state, commit them here.
+ // Note, we can't use PageAccessibilityDisposition::kAllowKeepForPerf, because
+ // we have no knowledge which pages have been committed before (it doesn't
+ // matter on Windows anyway).
+ if (kUseLazyCommit) {
+ const bool ok = root->TryRecommitSystemPagesForDataLocked(
+ commit_start, commit_end - commit_start,
+ PageAccessibilityDisposition::kRequireUpdate,
+ slot_size <= kMaxMemoryTaggingSize);
+ if (!ok) {
+ if (!ContainsFlags(flags, AllocFlags::kReturnNull)) {
+ ScopedUnlockGuard unlock{PartitionRootLock(root)};
+ PartitionOutOfMemoryCommitFailure(root, slot_size);
+ }
+ return 0;
+ }
+ }
+
// The slot being returned is considered allocated.
slot_span->num_allocated_slots++;
// Round down, because a slot that doesn't fully fit in the new page(s) isn't
@@ -948,19 +969,6 @@
slot_span->num_unprovisioned_slots <=
get_slots_per_span());
- // If lazy commit is enabled, meaning system pages in the slot span come
- // in an initially decommitted state, commit them here.
- // Note, we can't use PageAccessibilityDisposition::kAllowKeepForPerf, because
- // we have no knowledge which pages have been committed before (it doesn't
- // matter on Windows anyway).
- if (kUseLazyCommit) {
- // TODO(lizeb): Handle commit failure.
- root->RecommitSystemPagesForData(
- commit_start, commit_end - commit_start,
- PageAccessibilityDisposition::kRequireUpdate,
- slot_size <= kMaxMemoryTaggingSize);
- }
-
#if PA_CONFIG(HAS_MEMORY_TAGGING)
const bool use_tagging =
root->IsMemoryTaggingEnabled() && slot_size <= kMaxMemoryTaggingSize;
@@ -1299,7 +1307,7 @@
size_t slot_span_alignment,
bool* is_already_zeroed) {
PA_DCHECK((slot_span_alignment >= PartitionPageSize()) &&
- base::bits::IsPowerOfTwo(slot_span_alignment));
+ std::has_single_bit(slot_span_alignment));
// The slow path is called when the freelist is empty. The only exception is
// when a higher-order alignment is requested, in which case the freelist
@@ -1385,7 +1393,6 @@
new_slot_span = decommitted_slot_spans_head;
PA_DCHECK(new_slot_span->bucket == this);
PA_DCHECK(new_slot_span->is_decommitted());
- decommitted_slot_spans_head = new_slot_span->next_slot_span;
// If lazy commit is enabled, pages will be recommitted when provisioning
// slots, in ProvisionMoreSlotsAndAllocOne(), not here.
@@ -1396,13 +1403,21 @@
// pages have been previously committed, and then decommitted using
// PageAccessibilityDisposition::kAllowKeepForPerf, so use the
// same option as an optimization.
- // TODO(lizeb): Handle commit failure.
- root->RecommitSystemPagesForData(
+ const bool ok = root->TryRecommitSystemPagesForDataLocked(
slot_span_start, new_slot_span->bucket->get_bytes_per_span(),
PageAccessibilityDisposition::kAllowKeepForPerf,
slot_size <= kMaxMemoryTaggingSize);
+ if (!ok) {
+ if (!ContainsFlags(flags, AllocFlags::kReturnNull)) {
+ ScopedUnlockGuard unlock{PartitionRootLock(root)};
+ PartitionOutOfMemoryCommitFailure(
+ root, new_slot_span->bucket->get_bytes_per_span());
+ }
+ return 0;
+ }
}
+ decommitted_slot_spans_head = new_slot_span->next_slot_span;
new_slot_span->Reset();
*is_already_zeroed = DecommittedMemoryIsAlwaysZeroed();
}
@@ -1456,7 +1471,7 @@
// Otherwise, we need to provision more slots by committing more pages. Build
// the free list for the newly provisioned slots.
PA_DCHECK(new_slot_span->num_unprovisioned_slots);
- return ProvisionMoreSlotsAndAllocOne(root, new_slot_span);
+ return ProvisionMoreSlotsAndAllocOne(root, flags, new_slot_span);
}
uintptr_t PartitionBucket::AllocNewSuperPageSpanForGwpAsan(
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.h b/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.h
index 5a32154..ecb808f 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_bucket.h
@@ -217,6 +217,7 @@
// InitializeSlotSpan() first.
PA_ALWAYS_INLINE uintptr_t
ProvisionMoreSlotsAndAllocOne(PartitionRoot* root,
+ AllocFlags flags,
SlotSpanMetadata* slot_span)
PA_EXCLUSIVE_LOCKS_REQUIRED(PartitionRootLock(root));
};
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_bucket_lookup.h b/base/allocator/partition_allocator/src/partition_alloc/partition_bucket_lookup.h
index f23686a..181f2ac 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_bucket_lookup.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_bucket_lookup.h
@@ -208,14 +208,8 @@
bucket_index_lookup_[((kBitsPerSizeT + 1) * kNumBucketsPerOrder) + 1]{};
};
-PA_ALWAYS_INLINE constexpr size_t RoundUpToPowerOfTwo(size_t size) {
- const size_t n = 1 << base::bits::Log2Ceiling(static_cast<uint32_t>(size));
- PA_DCHECK(size <= n);
- return n;
-}
-
PA_ALWAYS_INLINE constexpr size_t RoundUpSize(size_t size) {
- const size_t next_power = RoundUpToPowerOfTwo(size);
+ const size_t next_power = std::bit_ceil(size);
const size_t prev_power = next_power >> 1;
PA_DCHECK(size <= next_power);
PA_DCHECK(prev_power < size);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_page.h b/base/allocator/partition_allocator/src/partition_alloc/partition_page.h
index 4a77782..ab1c9c2 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_page.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_page.h
@@ -362,11 +362,15 @@
// Certain functions rely on PartitionPage being either SlotSpanMetadata or
// SubsequentPageMetadata, and therefore freely casting between each other.
// TODO(https://crbug.com/1500662) Stop ignoring the -Winvalid-offsetof warning.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Winvalid-offsetof"
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Winvalid-offsetof"
+#endif
static_assert(offsetof(PartitionPage, slot_span_metadata) == 0, "");
static_assert(offsetof(PartitionPage, subsequent_page_metadata) == 0, "");
-#pragma GCC diagnostic pop
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
PA_ALWAYS_INLINE PartitionPage* PartitionSuperPageToMetadataArea(
uintptr_t super_page) {
@@ -915,8 +919,8 @@
Page::FromAddr(SuperPagePayloadBegin(super_page, with_quarantine));
auto* const last_page =
Page::FromAddr(SuperPagePayloadEnd(super_page) - PartitionPageSize());
- Page* page;
- SlotSpan* slot_span;
+ Page* page = nullptr;
+ SlotSpan* slot_span = nullptr;
for (page = first_page; page <= last_page;) {
PA_DCHECK(!page->slot_span_metadata_offset); // Ensure slot span beginning.
if (!page->is_valid) {
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc b/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc
index 25160d8..5943a76 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_root.cc
@@ -991,6 +991,8 @@
(opts.use_configurable_pool == PartitionOptions::kAllowed) &&
IsConfigurablePoolAvailable();
PA_DCHECK(!settings.use_configurable_pool || IsConfigurablePoolAvailable());
+ settings.zapping_by_free_flags =
+ opts.zapping_by_free_flags == PartitionOptions::kEnabled;
#if PA_CONFIG(HAS_MEMORY_TAGGING)
settings.memory_tagging_enabled_ =
opts.memory_tagging.enabled == PartitionOptions::kEnabled;
@@ -1132,12 +1134,21 @@
PartitionRoot::Settings::Settings() = default;
-PartitionRoot::PartitionRoot() : scheduler_loop_quarantine(this) {}
+PartitionRoot::PartitionRoot()
+ : scheduler_loop_quarantine_root(*this),
+ scheduler_loop_quarantine(
+ scheduler_loop_quarantine_root
+ .CreateBranch<internal::SchedulerLoopQuarantineBranch::
+ kQuarantineCapacityCount>()) {}
PartitionRoot::PartitionRoot(PartitionOptions opts)
- : scheduler_loop_quarantine(
- this,
- opts.scheduler_loop_quarantine_capacity_in_bytes) {
+ : scheduler_loop_quarantine_root(
+ *this,
+ opts.scheduler_loop_quarantine_capacity_in_bytes),
+ scheduler_loop_quarantine(
+ scheduler_loop_quarantine_root
+ .CreateBranch<internal::SchedulerLoopQuarantineBranch::
+ kQuarantineCapacityCount>()) {
Init(opts);
}
@@ -1316,7 +1327,7 @@
// statistics (and cookie, if present).
if (slot_span->CanStoreRawSize()) {
#if BUILDFLAG(PUT_REF_COUNT_IN_PREVIOUS_SLOT) && BUILDFLAG(PA_DCHECK_IS_ON)
- internal::PartitionRefCount* old_ref_count;
+ internal::PartitionRefCount* old_ref_count = nullptr;
if (brp_enabled()) {
old_ref_count = internal::PartitionRefCountPointer(slot_start);
}
@@ -1439,7 +1450,7 @@
}
PartitionBucketMemoryStats bucket_stats[internal::kNumBuckets];
size_t num_direct_mapped_allocations = 0;
- PartitionMemoryStats stats = {0};
+ PartitionMemoryStats stats = {};
stats.syscall_count = syscall_count.load(std::memory_order_relaxed);
stats.syscall_total_time_ns =
@@ -1707,6 +1718,11 @@
size_t);
#undef EXPORT_TEMPLATE
+// TODO(https://crbug.com/1500662) Stop ignoring the -Winvalid-offsetof warning.
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Winvalid-offsetof"
+#endif
static_assert(offsetof(PartitionRoot, sentinel_bucket) ==
offsetof(PartitionRoot, buckets) +
internal::kNumBuckets * sizeof(PartitionRoot::Bucket),
@@ -1715,5 +1731,8 @@
static_assert(
offsetof(PartitionRoot, lock_) >= 64,
"The lock should not be on the same cacheline as the read-mostly flags");
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
} // namespace partition_alloc
diff --git a/base/allocator/partition_allocator/src/partition_alloc/partition_root.h b/base/allocator/partition_allocator/src/partition_alloc/partition_root.h
index 9f42828..b7ea978 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/partition_root.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/partition_root.h
@@ -141,6 +141,14 @@
// Options struct used to configure PartitionRoot and PartitionAllocator.
struct PartitionOptions {
+ // Marked inline so that the chromium style plugin doesn't complain that a
+ // "complex constructor" has an inline body. This warning is disabled when
+ // the constructor is explicitly marked "inline". Note that this is a false
+ // positive of the plugin, since constexpr implies inline.
+ inline constexpr PartitionOptions();
+ inline constexpr PartitionOptions(const PartitionOptions& other);
+ inline constexpr ~PartitionOptions();
+
enum class AllowToggle : uint8_t {
kDisallowed,
kAllowed,
@@ -174,6 +182,8 @@
size_t scheduler_loop_quarantine_capacity_in_bytes = 0;
+ EnableToggle zapping_by_free_flags = kDisabled;
+
struct {
EnableToggle enabled = kDisabled;
TagViolationReportingMode reporting_mode =
@@ -188,6 +198,11 @@
#endif
};
+constexpr PartitionOptions::PartitionOptions() = default;
+constexpr PartitionOptions::PartitionOptions(const PartitionOptions& other) =
+ default;
+constexpr PartitionOptions::~PartitionOptions() = default;
+
// When/if free lists should be "straightened" when calling
// PartitionRoot::PurgeMemory(..., accounting_only=false).
enum class StraightenLargerSlotSpanFreeListsMode {
@@ -259,6 +274,7 @@
#endif // PA_CONFIG(ENABLE_MAC11_MALLOC_SIZE_HACK)
#endif // BUILDFLAG(ENABLE_BACKUP_REF_PTR_SUPPORT)
bool use_configurable_pool = false;
+ bool zapping_by_free_flags = false;
#if PA_CONFIG(HAS_MEMORY_TAGGING)
bool memory_tagging_enabled_ = false;
TagViolationReportingMode memory_tagging_reporting_mode_ =
@@ -370,9 +386,10 @@
bool quarantine_always_for_testing = false;
+ internal::LightweightQuarantineRoot scheduler_loop_quarantine_root;
// NoDestructor because we don't need to dequarantine objects as the root
// associated with it is dying anyway.
- internal::base::NoDestructor<internal::SchedulerLoopQuarantine>
+ internal::base::NoDestructor<internal::SchedulerLoopQuarantineBranch>
scheduler_loop_quarantine;
PartitionRoot();
@@ -439,13 +456,34 @@
PageAccessibilityDisposition accessibility_disposition,
bool request_tagging)
PA_EXCLUSIVE_LOCKS_REQUIRED(internal::PartitionRootLock(this));
- PA_ALWAYS_INLINE bool TryRecommitSystemPagesForData(
+
+ template <bool already_locked>
+ PA_ALWAYS_INLINE bool TryRecommitSystemPagesForDataInternal(
+ uintptr_t address,
+ size_t length,
+ PageAccessibilityDisposition accessibility_disposition,
+ bool request_tagging);
+
+ // TryRecommitSystemPagesForDataWithAcquiringLock() locks this root internally
+ // before invoking DecommitEmptySlotSpans(), which needs the lock. So the root
+ // must not be locked when invoking this method.
+ PA_ALWAYS_INLINE bool TryRecommitSystemPagesForDataWithAcquiringLock(
uintptr_t address,
size_t length,
PageAccessibilityDisposition accessibility_disposition,
bool request_tagging)
PA_LOCKS_EXCLUDED(internal::PartitionRootLock(this));
+ // TryRecommitSystemPagesForDataLocked() doesn't lock this root internally
+ // before invoking DecommitEmptySlotSpans(), which needs the lock. So the root
+ // must have been already locked when invoking this method.
+ PA_ALWAYS_INLINE bool TryRecommitSystemPagesForDataLocked(
+ uintptr_t address,
+ size_t length,
+ PageAccessibilityDisposition accessibility_disposition,
+ bool request_tagging)
+ PA_EXCLUSIVE_LOCKS_REQUIRED(internal::PartitionRootLock(this));
+
[[noreturn]] PA_NOINLINE void OutOfMemory(size_t size);
// Returns a pointer aligned on |alignment|, or nullptr.
@@ -842,7 +880,8 @@
return straighten_larger_slot_span_free_lists_;
}
- internal::SchedulerLoopQuarantine& GetSchedulerLoopQuarantineForTesting() {
+ internal::SchedulerLoopQuarantineBranch&
+ GetSchedulerLoopQuarantineBranchForTesting() {
// TODO(crbug.com/1462223): Implement thread-local version and return it
// here.
return *scheduler_loop_quarantine;
@@ -971,8 +1010,8 @@
PA_ALWAYS_INLINE ThreadCache* GetOrCreateThreadCache();
PA_ALWAYS_INLINE ThreadCache* GetThreadCache();
- PA_ALWAYS_INLINE internal::SchedulerLoopQuarantine&
- GetSchedulerLoopQuarantine();
+ PA_ALWAYS_INLINE internal::SchedulerLoopQuarantineBranch&
+ GetSchedulerLoopQuarantineBranch();
PA_ALWAYS_INLINE AllocationNotificationData
CreateAllocationNotificationData(void* object,
@@ -1186,7 +1225,7 @@
size_t* usable_size,
bool* is_already_zeroed) {
PA_DCHECK((slot_span_alignment >= internal::PartitionPageSize()) &&
- internal::base::bits::IsPowerOfTwo(slot_span_alignment));
+ std::has_single_bit(slot_span_alignment));
SlotSpan* slot_span = bucket->active_slot_spans_head;
// There always must be a slot span on the active list (could be a sentinel).
PA_DCHECK(slot_span);
@@ -1377,18 +1416,20 @@
}
if constexpr (ContainsFlags(flags, FreeFlags::kZap)) {
- SlotSpan* slot_span = SlotSpan::FromObject(object);
- uintptr_t slot_start = ObjectToSlotStart(object);
- internal::SecureMemset(internal::SlotStartAddr2Ptr(slot_start),
- internal::kFreedByte, GetSlotUsableSize(slot_span));
+ if (settings.zapping_by_free_flags) {
+ SlotSpan* slot_span = SlotSpan::FromObject(object);
+ uintptr_t slot_start = ObjectToSlotStart(object);
+ internal::SecureMemset(internal::SlotStartAddr2Ptr(slot_start),
+ internal::kFreedByte,
+ GetSlotUsableSize(slot_span));
+ }
}
// TODO(https://crbug.com/1497380): Collecting objects for
- // `kSchedulerLoopQuarantine` here means it "delays" other checks (BRP
+ // `kSchedulerLoopQuarantineBranch` here means it "delays" other checks (BRP
// refcount, cookie, etc.)
// For better debuggability, we should do these checks before quarantining.
if constexpr (ContainsFlags(flags, FreeFlags::kSchedulerLoopQuarantine)) {
- GetSchedulerLoopQuarantine().Quarantine(
- internal::LightweightQuarantineEntry(object));
+ GetSchedulerLoopQuarantineBranch().Quarantine(object);
return;
}
@@ -1816,7 +1857,8 @@
IncreaseCommittedPages(length);
}
-PA_ALWAYS_INLINE bool PartitionRoot::TryRecommitSystemPagesForData(
+template <bool already_locked>
+PA_ALWAYS_INLINE bool PartitionRoot::TryRecommitSystemPagesForDataInternal(
uintptr_t address,
size_t length,
PageAccessibilityDisposition accessibility_disposition,
@@ -1827,11 +1869,16 @@
bool ok = TryRecommitSystemPages(address, length, page_accessibility,
accessibility_disposition);
if (PA_UNLIKELY(!ok)) {
- // Decommit some memory and retry. The alternative is crashing.
{
- ::partition_alloc::internal::ScopedGuard guard(
- internal::PartitionRootLock(this));
- DecommitEmptySlotSpans();
+ // Decommit some memory and retry. The alternative is crashing.
+ if constexpr (!already_locked) {
+ ::partition_alloc::internal::ScopedGuard guard(
+ internal::PartitionRootLock(this));
+ DecommitEmptySlotSpans();
+ } else {
+ internal::PartitionRootLock(this).AssertAcquired();
+ DecommitEmptySlotSpans();
+ }
}
ok = TryRecommitSystemPages(address, length, page_accessibility,
accessibility_disposition);
@@ -1844,6 +1891,26 @@
return ok;
}
+PA_ALWAYS_INLINE bool
+PartitionRoot::TryRecommitSystemPagesForDataWithAcquiringLock(
+ uintptr_t address,
+ size_t length,
+ PageAccessibilityDisposition accessibility_disposition,
+ bool request_tagging) {
+ return TryRecommitSystemPagesForDataInternal<false>(
+ address, length, accessibility_disposition, request_tagging);
+}
+
+PA_ALWAYS_INLINE
+bool PartitionRoot::TryRecommitSystemPagesForDataLocked(
+ uintptr_t address,
+ size_t length,
+ PageAccessibilityDisposition accessibility_disposition,
+ bool request_tagging) {
+ return TryRecommitSystemPagesForDataInternal<true>(
+ address, length, accessibility_disposition, request_tagging);
+}
+
// static
//
// Returns the size available to the app. It can be equal or higher than the
@@ -1947,9 +2014,8 @@
size_t slot_span_alignment,
const char* type_name) {
static_assert(AreValidFlags(flags));
- PA_DCHECK(
- (slot_span_alignment >= internal::PartitionPageSize()) &&
- partition_alloc::internal::base::bits::IsPowerOfTwo(slot_span_alignment));
+ PA_DCHECK((slot_span_alignment >= internal::PartitionPageSize()) &&
+ std::has_single_bit(slot_span_alignment));
static_assert(!ContainsFlags(
flags, AllocFlags::kMemoryShouldBeTaggedForMte)); // Internal only.
@@ -2250,7 +2316,7 @@
PA_DCHECK(settings.allow_aligned_alloc);
PA_DCHECK(!settings.extras_offset);
// This is mandated by |posix_memalign()|, so should never fire.
- PA_CHECK(partition_alloc::internal::base::bits::IsPowerOfTwo(alignment));
+ PA_CHECK(std::has_single_bit(alignment));
// Catch unsupported alignment requests early.
PA_CHECK(alignment <= internal::kMaxSupportedAlignment);
size_t raw_size = AdjustSizeForExtrasAdd(requested_size);
@@ -2269,7 +2335,7 @@
raw_size = static_cast<size_t>(1)
<< (int{sizeof(size_t) * 8} - std::countl_zero(raw_size - 1));
}
- PA_DCHECK(partition_alloc::internal::base::bits::IsPowerOfTwo(raw_size));
+ PA_DCHECK(std::has_single_bit(raw_size));
// Adjust back, because AllocInternalNoHooks/Alloc will adjust it again.
adjusted_size = AdjustSizeForExtrasSubtract(raw_size);
@@ -2291,9 +2357,8 @@
// don't pass anything less, because it'll mess up callee's calculations.
size_t slot_span_alignment =
std::max(alignment, internal::PartitionPageSize());
- // TODO(mikt): Investigate why all flags except kNoHooks are ignored here.
- void* object = AllocInternal<flags & AllocFlags::kNoHooks>(
- adjusted_size, slot_span_alignment, nullptr);
+ void* object =
+ AllocInternal<flags>(adjusted_size, slot_span_alignment, nullptr);
// |alignment| is a power of two, but the compiler doesn't necessarily know
// that. A regular % operation is very slow, make sure to use the equivalent,
@@ -2443,7 +2508,8 @@
}
// private.
-internal::SchedulerLoopQuarantine& PartitionRoot::GetSchedulerLoopQuarantine() {
+internal::SchedulerLoopQuarantineBranch&
+PartitionRoot::GetSchedulerLoopQuarantineBranch() {
// TODO(crbug.com/1462223): Implement thread-local version and return it here.
return *scheduler_loop_quarantine;
}
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h
index 9aa05b8..35e5b71 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr.h
@@ -271,6 +271,15 @@
test::RawPtrCountingImplForTest,
UnderlyingImplForTraits<Traits>>;
+// `kTypeTraits` is a customization interface to accosiate `T` with some
+// `RawPtrTraits`. Users may create specialization of this variable
+// to enable some traits by default.
+// Note that specialization must be declared before the first use that would
+// cause implicit instantiation of `raw_ptr` or `raw_ref`, in every translation
+// unit where such use occurs.
+template <typename T, typename SFINAE = void>
+constexpr inline auto kTypeTraits = RawPtrTraits::kEmpty;
+
} // namespace raw_ptr_traits
// `raw_ptr<T>` is a non-owning smart pointer that has improved memory-safety
@@ -283,9 +292,12 @@
// non-default move constructor/assignment. Thus, it's possible to get an error
// where the pointer is not actually dangling, and have to work around the
// compiler. We have not managed to construct such an example in Chromium yet.
-template <typename T, RawPtrTraits Traits = RawPtrTraits::kEmpty>
+template <typename T, RawPtrTraits PointerTraits = RawPtrTraits::kEmpty>
class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ptr {
public:
+ // Users may specify `RawPtrTraits` via raw_ptr's second template parameter
+ // `PointerTraits`, or specialization of `raw_ptr_traits::kTypeTraits<T>`.
+ constexpr static auto Traits = PointerTraits | raw_ptr_traits::kTypeTraits<T>;
using Impl = typename raw_ptr_traits::ImplForTraits<Traits>;
// Needed to make gtest Pointee matcher work with raw_ptr.
using element_type = T;
@@ -416,14 +428,15 @@
PA_ALWAYS_INLINE constexpr explicit raw_ptr(
const raw_ptr<T, PassedTraits>& p) noexcept
: wrapped_ptr_(Impl::WrapRawPtrForDuplication(
- raw_ptr_traits::ImplForTraits<PassedTraits>::
+ raw_ptr_traits::ImplForTraits<raw_ptr<T, PassedTraits>::Traits>::
UnsafelyUnwrapPtrForDuplication(p.wrapped_ptr_))) {
// Limit cross-kind conversions only to cases where kMayDangle gets added,
// because that's needed for Unretained(Ref)Wrapper. Use a static_assert,
// instead of disabling via SFINAE, so that the compiler catches other
// conversions. Otherwise implicit raw_ptr<T> -> T* -> raw_ptr<> route will
// be taken.
- static_assert(Traits == (PassedTraits | RawPtrTraits::kMayDangle));
+ static_assert(Traits == (raw_ptr<T, PassedTraits>::Traits |
+ RawPtrTraits::kMayDangle));
}
// Cross-kind assignment.
@@ -438,12 +451,13 @@
// instead of disabling via SFINAE, so that the compiler catches other
// conversions. Otherwise implicit raw_ptr<T> -> T* -> raw_ptr<> route will
// be taken.
- static_assert(Traits == (PassedTraits | RawPtrTraits::kMayDangle));
+ static_assert(Traits == (raw_ptr<T, PassedTraits>::Traits |
+ RawPtrTraits::kMayDangle));
Impl::ReleaseWrappedPtr(wrapped_ptr_);
wrapped_ptr_ = Impl::WrapRawPtrForDuplication(
- raw_ptr_traits::ImplForTraits<
- PassedTraits>::UnsafelyUnwrapPtrForDuplication(p.wrapped_ptr_));
+ raw_ptr_traits::ImplForTraits<raw_ptr<T, PassedTraits>::Traits>::
+ UnsafelyUnwrapPtrForDuplication(p.wrapped_ptr_));
return *this;
}
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc
index db3878e..9f2d79e 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc
+++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_nocompile.nc
@@ -116,9 +116,9 @@
DanglingPtrA ptr_a1 = new TypeA();
DanglingPtrB ptr_b1 = new TypeB();
raw_ptr<TypeA> ptr_a2 = ptr_a1; // expected-error {{no viable conversion from 'raw_ptr<[...], base::RawPtrTraits::kMayDangle aka 1>' to 'raw_ptr<[...], (default) RawPtrTraits::kEmpty aka 0>'}}
- raw_ptr<TypeA> ptr_a3(ptr_a1); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)0U == ((partition_alloc::internal::RawPtrTraits)1U | RawPtrTraits::kMayDangle)'}}
+ raw_ptr<TypeA> ptr_a3(ptr_a1); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeA, partition_alloc::internal::RawPtrTraits::kMayDangle>::Traits | RawPtrTraits::kMayDangle)'}}
raw_ptr<TypeA> ptr_a4 = std::move(ptr_a1); // expected-error {{no viable conversion from '__libcpp_remove_reference_t<raw_ptr<TypeA, partition_alloc::internal::RawPtrTraits::kMayDangle> &>' (aka 'base::raw_ptr<(anonymous namespace)::TypeA, partition_alloc::internal::RawPtrTraits::kMayDangle>') to 'raw_ptr<TypeA>'}}
- raw_ptr<TypeB> ptr_b2(std::move(ptr_b1)); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)0U == ((partition_alloc::internal::RawPtrTraits)1U | RawPtrTraits::kMayDangle)'}}
+ raw_ptr<TypeB> ptr_b2(std::move(ptr_b1)); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeB, partition_alloc::internal::RawPtrTraits::kMayDangle>::Traits | RawPtrTraits::kMayDangle)'}}
}
void CrossKindConversionFromDummy() {
@@ -126,9 +126,9 @@
raw_ptr<TypeA, base::RawPtrTraits::kDummyForTest> ptr_a1 = new TypeA();
raw_ptr<TypeB, base::RawPtrTraits::kDummyForTest> ptr_b1 = new TypeB();
DanglingPtrA ptr_a2 = ptr_a1; // expected-error {{no viable conversion from 'raw_ptr<[...], base::RawPtrTraits::kDummyForTest aka 2048>' to 'raw_ptr<[...], base::RawPtrTraits::kMayDangle aka 1>'}}
- DanglingPtrA ptr_a3(ptr_a1); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)1U == ((partition_alloc::internal::RawPtrTraits)2048U | RawPtrTraits::kMayDangle)'}}
+ DanglingPtrA ptr_a3(ptr_a1); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeA, partition_alloc::internal::RawPtrTraits::kDummyForTest>::Traits | RawPtrTraits::kMayDangle)'}}
DanglingPtrA ptr_a4 = std::move(ptr_a1); // expected-error {{no viable conversion from '__libcpp_remove_reference_t<raw_ptr<TypeA, partition_alloc::internal::RawPtrTraits::kDummyForTest> &>' (aka 'base::raw_ptr<(anonymous namespace)::TypeA, partition_alloc::internal::RawPtrTraits::kDummyForTest>') to 'DanglingPtrA' (aka 'raw_ptr<TypeA, base::RawPtrTraits::kMayDangle>')}}
- DanglingPtrB ptr_b2(std::move(ptr_b1)); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)1U == ((partition_alloc::internal::RawPtrTraits)2048U | RawPtrTraits::kMayDangle)'}}
+ DanglingPtrB ptr_b2(std::move(ptr_b1)); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeB, partition_alloc::internal::RawPtrTraits::kDummyForTest>::Traits | RawPtrTraits::kMayDangle)'}}
}
} // namespace
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc
index 4f30fda..9f6ee98 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ptr_unittest.cc
@@ -168,6 +168,28 @@
}());
#endif
+struct StructWithoutTypeBasedTraits {};
+struct BaseWithTypeBasedTraits {};
+struct DerivedWithTypeBasedTraits : BaseWithTypeBasedTraits {};
+
+namespace base::raw_ptr_traits {
+// `BaseWithTypeBasedTraits` and any derived classes have
+// `RawPtrTraits::kDummyForTest`.
+template <typename T>
+constexpr auto kTypeTraits<
+ T,
+ std::enable_if_t<std::is_base_of_v<BaseWithTypeBasedTraits, T>>> =
+ RawPtrTraits::kDummyForTest;
+} // namespace base::raw_ptr_traits
+
+// `raw_ptr<T>` should have traits based on specialization of `kTypeTraits<T>`.
+static_assert(!ContainsFlags(raw_ptr<StructWithoutTypeBasedTraits>::Traits,
+ base::RawPtrTraits::kDummyForTest));
+static_assert(ContainsFlags(raw_ptr<BaseWithTypeBasedTraits>::Traits,
+ base::RawPtrTraits::kDummyForTest));
+static_assert(ContainsFlags(raw_ptr<DerivedWithTypeBasedTraits>::Traits,
+ base::RawPtrTraits::kDummyForTest));
+
// Don't use base::internal for testing raw_ptr API, to test if code outside
// this namespace calls the correct functions from this namespace.
namespace {
@@ -1585,12 +1607,15 @@
}
partition_alloc::PartitionAllocator allocator_ =
- partition_alloc::PartitionAllocator(partition_alloc::PartitionOptions{
- .backup_ref_ptr = partition_alloc::PartitionOptions::kEnabled,
- .memory_tagging = {
- .enabled = base::CPU::GetInstanceNoAllocation().has_mte()
- ? partition_alloc::PartitionOptions::kEnabled
- : partition_alloc::PartitionOptions::kDisabled}});
+ partition_alloc::PartitionAllocator([]() {
+ partition_alloc::PartitionOptions opts;
+ opts.backup_ref_ptr = partition_alloc::PartitionOptions::kEnabled;
+ opts.memory_tagging = {
+ .enabled = base::CPU::GetInstanceNoAllocation().has_mte()
+ ? partition_alloc::PartitionOptions::kEnabled
+ : partition_alloc::PartitionOptions::kDisabled};
+ return opts;
+ }());
};
TEST_F(BackupRefPtrTest, Basic) {
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h
index f389761..ea2b613 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref.h
@@ -53,8 +53,15 @@
// Unlike a native `T&` reference, a mutable `raw_ref<T>` can be changed
// independent of the underlying `T`, similar to `std::reference_wrapper`. That
// means the reference inside it can be moved and reassigned.
-template <class T, RawPtrTraits Traits = RawPtrTraits::kEmpty>
+template <class T, RawPtrTraits ReferenceTraits = RawPtrTraits::kEmpty>
class PA_TRIVIAL_ABI PA_GSL_POINTER raw_ref {
+ public:
+ // Users may specify `RawPtrTraits` via raw_ref's second template parameter
+ // `ReferenceTraits`, or specialization of `raw_ptr_traits::kTypeTraits<T>`.
+ constexpr static auto Traits =
+ ReferenceTraits | raw_ptr_traits::kTypeTraits<T>;
+
+ private:
// operator* is used with the expectation of GetForExtraction semantics:
//
// raw_ref<Foo> foo_raw_ref = something;
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc
index 56c83f1..e4e9b02 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc
+++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_nocompile.nc
@@ -31,10 +31,10 @@
DanglingRefB ref_b1(b);
DanglingRefC ref_c1(c);
DanglingRefD ref_d1(d);
- raw_ref<TypeA> ref_a2 = ref_a1; // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)4U == ((partition_alloc::internal::RawPtrTraits)5U | RawPtrTraits::kMayDangle)'}}
- raw_ref<TypeB> ref_b2(ref_b1); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)4U == ((partition_alloc::internal::RawPtrTraits)5U | RawPtrTraits::kMayDangle)'}}
- raw_ref<TypeC> ref_c2 = std::move(ref_c1); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)4U == ((partition_alloc::internal::RawPtrTraits)5U | RawPtrTraits::kMayDangle)'}}
- raw_ref<TypeD> ref_d2(std::move(ref_d1)); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)4U == ((partition_alloc::internal::RawPtrTraits)5U | RawPtrTraits::kMayDangle)'}}
+ raw_ref<TypeA> ref_a2 = ref_a1; // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeA, 5>::Traits | RawPtrTraits::kMayDangle)'}}
+ raw_ref<TypeB> ref_b2(ref_b1); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeB, 5>::Traits | RawPtrTraits::kMayDangle)'}}
+ raw_ref<TypeC> ref_c2 = std::move(ref_c1); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeC, 5>::Traits | RawPtrTraits::kMayDangle)'}}
+ raw_ref<TypeD> ref_d2(std::move(ref_d1)); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeD, 5>::Traits | RawPtrTraits::kMayDangle)'}}
}
void CrossKindConversionFromDummy() {
@@ -47,10 +47,10 @@
raw_ref<TypeB, base::RawPtrTraits::kDummyForTest> ref_b1(b);
raw_ref<TypeC, base::RawPtrTraits::kDummyForTest> ref_c1(c);
raw_ref<TypeD, base::RawPtrTraits::kDummyForTest> ref_d1(d);
- DanglingRefA ref_a2 = ref_a1; // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)5U == ((partition_alloc::internal::RawPtrTraits)2052U | RawPtrTraits::kMayDangle)'}}
- DanglingRefB ref_b3(ref_b1); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)5U == ((partition_alloc::internal::RawPtrTraits)2052U | RawPtrTraits::kMayDangle)'}}
- DanglingRefC ref_c2 = std::move(ref_c1); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)5U == ((partition_alloc::internal::RawPtrTraits)2052U | RawPtrTraits::kMayDangle)'}}
- DanglingRefD ref_d2(std::move(ref_d1)); // expected-error@*:* {{static assertion failed due to requirement '(partition_alloc::internal::RawPtrTraits)5U == ((partition_alloc::internal::RawPtrTraits)2052U | RawPtrTraits::kMayDangle)'}}
+ DanglingRefA ref_a2 = ref_a1; // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeA, 2052>::Traits | RawPtrTraits::kMayDangle)'}}
+ DanglingRefB ref_b3(ref_b1); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeB, 2052>::Traits | RawPtrTraits::kMayDangle)'}}
+ DanglingRefC ref_c2 = std::move(ref_c1); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeC, 2052>::Traits | RawPtrTraits::kMayDangle)'}}
+ DanglingRefD ref_d2(std::move(ref_d1)); // expected-error@*:* {{static assertion failed due to requirement 'Traits == (raw_ptr<(anonymous namespace)::TypeD, 2052>::Traits | RawPtrTraits::kMayDangle)'}}
}
} // namespace
diff --git a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_unittest.cc
index 6daaab6..b1f80e1 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/pointers/raw_ref_unittest.cc
@@ -195,6 +195,32 @@
}());
#endif
+struct StructWithoutTypeBasedTraits {};
+struct BaseWithTypeBasedTraits {};
+struct DerivedWithTypeBasedTraits : BaseWithTypeBasedTraits {};
+
+} // namespace
+
+namespace base::raw_ptr_traits {
+// `BaseWithTypeBasedTraits` and any derived classes have
+// `RawPtrTraits::kDummyForTest`.
+template <typename T>
+constexpr auto kTypeTraits<
+ T,
+ std::enable_if_t<std::is_base_of_v<BaseWithTypeBasedTraits, T>>> =
+ RawPtrTraits::kDummyForTest;
+} // namespace base::raw_ptr_traits
+
+// `raw_ptr<T>` should have traits based on specialization of `kTypeTraits<T>`.
+static_assert(!ContainsFlags(raw_ref<StructWithoutTypeBasedTraits>::Traits,
+ base::RawPtrTraits::kDummyForTest));
+static_assert(ContainsFlags(raw_ref<BaseWithTypeBasedTraits>::Traits,
+ base::RawPtrTraits::kDummyForTest));
+static_assert(ContainsFlags(raw_ref<DerivedWithTypeBasedTraits>::Traits,
+ base::RawPtrTraits::kDummyForTest));
+
+namespace {
+
TEST(RawRef, Construct) {
int i = 1;
auto r = raw_ref<int>(i);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.mm b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.mm
index 63bc559..f23ad5b 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.mm
+++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_interception_apple.mm
@@ -28,12 +28,12 @@
#include <stddef.h>
#include <algorithm>
+#include <bit>
#include <new>
#include "build/build_config.h"
#include "partition_alloc/oom.h"
#include "partition_alloc/partition_alloc_base/apple/mach_logging.h"
-#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/logging.h"
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/shim/malloc_zone_functions_apple.h"
@@ -182,7 +182,7 @@
// other reasons why null might be returned. See posix_memalign() in 10.15's
// https://opensource.apple.com/source/libmalloc/libmalloc-283/src/malloc.c .
if (!result && size && alignment >= sizeof(void*) &&
- partition_alloc::internal::base::bits::IsPowerOfTwo(alignment)) {
+ std::has_single_bit(alignment)) {
partition_alloc::TerminateBecauseOutOfMemory(size);
}
return result;
@@ -238,7 +238,7 @@
// other reasons why null might be returned. See posix_memalign() in 10.15's
// https://opensource.apple.com/source/libmalloc/libmalloc-283/src/malloc.c .
if (!result && size && alignment >= sizeof(void*) &&
- partition_alloc::internal::base::bits::IsPowerOfTwo(alignment)) {
+ std::has_single_bit(alignment)) {
partition_alloc::TerminateBecauseOutOfMemory(size);
}
return result;
diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc
index 6b8914d..1a5c163 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.cc
@@ -7,6 +7,7 @@
#include <errno.h>
#include <atomic>
+#include <bit>
#include <new>
#include "build/build_config.h"
@@ -273,8 +274,7 @@
size_t size) {
// posix_memalign is supposed to check the arguments. See tc_posix_memalign()
// in tc_malloc.cc.
- if (((alignment % sizeof(void*)) != 0) ||
- !partition_alloc::internal::base::bits::IsPowerOfTwo(alignment)) {
+ if (((alignment % sizeof(void*)) != 0) || !std::has_single_bit(alignment)) {
return EINVAL;
}
void* ptr = ShimMemalign(alignment, size, nullptr);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h
index a712cfc..24b622c 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim.h
@@ -197,6 +197,9 @@
using UseDedicatedAlignedPartition = partition_alloc::internal::base::
StrongAlias<class UseDedicatedAlignedPartitionTag, bool>;
enum class BucketDistribution : uint8_t { kNeutral, kDenser };
+using ZappingByFreeFlags =
+ partition_alloc::internal::base::StrongAlias<class ZappingByFreeFlagsTag,
+ bool>;
// If |thread_cache_on_non_quarantinable_partition| is specified, the
// thread-cache will be enabled on the non-quarantinable partition. The
@@ -210,7 +213,8 @@
UseDedicatedAlignedPartition use_dedicated_aligned_partition,
size_t ref_count_size,
BucketDistribution distribution,
- size_t scheduler_loop_quarantine_capacity_in_bytes);
+ size_t scheduler_loop_quarantine_capacity_in_bytes,
+ ZappingByFreeFlags zapping_by_free_flags);
// If |thread_cache_on_non_quarantinable_partition| is specified, the
// thread-cache will be enabled on the non-quarantinable partition. The
diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
index 396231c..38f2e5c 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.cc
@@ -5,6 +5,7 @@
#include "partition_alloc/shim/allocator_shim_default_dispatch_to_partition_alloc.h"
#include <atomic>
+#include <bit>
#include <cstddef>
#include <map>
#include <string>
@@ -15,7 +16,6 @@
#include "partition_alloc/chromecast_buildflags.h"
#include "partition_alloc/memory_reclaimer.h"
#include "partition_alloc/partition_alloc.h"
-#include "partition_alloc/partition_alloc_base/bits.h"
#include "partition_alloc/partition_alloc_base/compiler_specific.h"
#include "partition_alloc/partition_alloc_base/no_destructor.h"
#include "partition_alloc/partition_alloc_base/numerics/checked_math.h"
@@ -154,13 +154,12 @@
// and only one is supported at a time.
partition_alloc::PartitionOptions::kDisabled;
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
- auto* new_root = new (buffer)
- partition_alloc::PartitionRoot(partition_alloc::PartitionOptions{
- .aligned_alloc = partition_alloc::PartitionOptions::kAllowed,
- .thread_cache = thread_cache,
- .star_scan_quarantine = partition_alloc::PartitionOptions::kAllowed,
- .backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled,
- });
+ partition_alloc::PartitionOptions opts;
+ opts.aligned_alloc = partition_alloc::PartitionOptions::kAllowed;
+ opts.thread_cache = thread_cache;
+ opts.star_scan_quarantine = partition_alloc::PartitionOptions::kAllowed;
+ opts.backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled;
+ auto* new_root = new (buffer) partition_alloc::PartitionRoot(opts);
return new_root;
}
@@ -219,7 +218,7 @@
// mismatch. (see below the default_dispatch definition).
if (alignment <= partition_alloc::internal::kAlignment) {
// This is mandated by |posix_memalign()| and friends, so should never fire.
- PA_CHECK(partition_alloc::internal::base::bits::IsPowerOfTwo(alignment));
+ PA_CHECK(std::has_single_bit(alignment));
// TODO(bartekn): See if the compiler optimizes branches down the stack on
// Mac, where PartitionPageSize() isn't constexpr.
return Allocator()->AllocInline<partition_alloc::AllocFlags::kNoHooks>(
@@ -530,7 +529,8 @@
UseDedicatedAlignedPartition use_dedicated_aligned_partition,
size_t ref_count_size,
BucketDistribution distribution,
- size_t scheduler_loop_quarantine_capacity_in_bytes) {
+ size_t scheduler_loop_quarantine_capacity_in_bytes,
+ ZappingByFreeFlags zapping_by_free_flags) {
// BRP cannot be enabled without splitting the main partition. Furthermore, in
// the "before allocation" mode, it can't be enabled without further splitting
// out the aligned partition.
@@ -572,23 +572,31 @@
// shouldn't bite us here. Mentioning just in case we move this code earlier.
static partition_alloc::internal::base::NoDestructor<
partition_alloc::PartitionAllocator>
- new_main_allocator(partition_alloc::PartitionOptions{
- .aligned_alloc = !use_dedicated_aligned_partition
- ? partition_alloc::PartitionOptions::kAllowed
- : partition_alloc::PartitionOptions::kDisallowed,
- .thread_cache = partition_alloc::PartitionOptions::kDisabled,
- .star_scan_quarantine = partition_alloc::PartitionOptions::kAllowed,
- .backup_ref_ptr = enable_brp
- ? partition_alloc::PartitionOptions::kEnabled
- : partition_alloc::PartitionOptions::kDisabled,
- .ref_count_size = ref_count_size,
- .scheduler_loop_quarantine_capacity_in_bytes =
- scheduler_loop_quarantine_capacity_in_bytes,
- .memory_tagging = {
- .enabled = enable_memory_tagging
- ? partition_alloc::PartitionOptions::kEnabled
- : partition_alloc::PartitionOptions::kDisabled,
- .reporting_mode = memory_tagging_reporting_mode}});
+ new_main_allocator([&]() {
+ partition_alloc::PartitionOptions opts;
+ opts.aligned_alloc =
+ !use_dedicated_aligned_partition
+ ? partition_alloc::PartitionOptions::kAllowed
+ : partition_alloc::PartitionOptions::kDisallowed;
+ opts.thread_cache = partition_alloc::PartitionOptions::kDisabled;
+ opts.star_scan_quarantine = partition_alloc::PartitionOptions::kAllowed;
+ opts.backup_ref_ptr =
+ enable_brp ? partition_alloc::PartitionOptions::kEnabled
+ : partition_alloc::PartitionOptions::kDisabled;
+ opts.ref_count_size = ref_count_size;
+ opts.zapping_by_free_flags =
+ zapping_by_free_flags
+ ? partition_alloc::PartitionOptions::kEnabled
+ : partition_alloc::PartitionOptions::kDisabled;
+ opts.scheduler_loop_quarantine_capacity_in_bytes =
+ scheduler_loop_quarantine_capacity_in_bytes;
+ opts.memory_tagging = {
+ .enabled = enable_memory_tagging
+ ? partition_alloc::PartitionOptions::kEnabled
+ : partition_alloc::PartitionOptions::kDisabled,
+ .reporting_mode = memory_tagging_reporting_mode};
+ return opts;
+ }());
partition_alloc::PartitionRoot* new_root = new_main_allocator->root();
partition_alloc::PartitionRoot* new_aligned_root;
@@ -597,12 +605,15 @@
// result in one less partition, but come at a cost of commingling types.
static partition_alloc::internal::base::NoDestructor<
partition_alloc::PartitionAllocator>
- new_aligned_allocator(partition_alloc::PartitionOptions{
- .aligned_alloc = partition_alloc::PartitionOptions::kAllowed,
- .thread_cache = partition_alloc::PartitionOptions::kDisabled,
- .star_scan_quarantine = partition_alloc::PartitionOptions::kAllowed,
- .backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled,
- });
+ new_aligned_allocator([&]() {
+ partition_alloc::PartitionOptions opts;
+ opts.aligned_alloc = partition_alloc::PartitionOptions::kAllowed;
+ opts.thread_cache = partition_alloc::PartitionOptions::kDisabled;
+ opts.star_scan_quarantine =
+ partition_alloc::PartitionOptions::kAllowed;
+ opts.backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled;
+ return opts;
+ }());
new_aligned_root = new_aligned_allocator->root();
} else {
// The new main root can also support AlignedAlloc.
@@ -656,13 +667,15 @@
? partition_alloc::TagViolationReportingMode::kSynchronous
: partition_alloc::TagViolationReportingMode::kDisabled;
- // We don't use this feature in PDFium.
+ // We don't use these features in PDFium.
size_t scheduler_loop_quarantine_capacity_in_bytes = 0;
+ auto zapping_by_free_flags = ZappingByFreeFlags(false);
- ConfigurePartitions(
- enable_brp, enable_memory_tagging, memory_tagging_reporting_mode,
- split_main_partition, use_dedicated_aligned_partition, ref_count_size,
- distribution, scheduler_loop_quarantine_capacity_in_bytes);
+ ConfigurePartitions(enable_brp, enable_memory_tagging,
+ memory_tagging_reporting_mode, split_main_partition,
+ use_dedicated_aligned_partition, ref_count_size,
+ distribution, scheduler_loop_quarantine_capacity_in_bytes,
+ zapping_by_free_flags);
}
// No synchronization provided: `PartitionRoot.flags` is only written
@@ -779,7 +792,7 @@
&nonquarantinable_allocator_dumper);
}
- struct mallinfo info = {0};
+ struct mallinfo info = {};
info.arena = 0; // Memory *not* allocated with mmap().
// Memory allocated with mmap(), aka virtual size.
diff --git a/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.cc b/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.cc
index 06046c4..7aa8c86 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/shim/nonscannable_allocator.cc
@@ -63,14 +63,13 @@
template <bool quarantinable>
void NonScannableAllocatorImpl<quarantinable>::NotifyPCScanEnabled() {
#if BUILDFLAG(USE_STARSCAN)
+ partition_alloc::PartitionOptions opts;
+ opts.star_scan_quarantine =
+ quarantinable ? partition_alloc::PartitionOptions::kAllowed
+ : partition_alloc::PartitionOptions::kDisallowed;
+ opts.backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled;
allocator_.reset(partition_alloc::internal::MakePCScanMetadata<
- partition_alloc::PartitionAllocator>(
- partition_alloc::PartitionOptions{
- .star_scan_quarantine =
- quarantinable ? partition_alloc::PartitionOptions::kAllowed
- : partition_alloc::PartitionOptions::kDisallowed,
- .backup_ref_ptr = partition_alloc::PartitionOptions::kDisabled,
- }));
+ partition_alloc::PartitionAllocator>(opts));
if constexpr (quarantinable) {
partition_alloc::internal::PCScan::RegisterNonScannableRoot(
allocator_->root());
diff --git a/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_unittest.cc
index 133dc31..b26ca89 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/starscan/pcscan_unittest.cc
@@ -51,14 +51,16 @@
class PartitionAllocPCScanTestBase : public testing::Test {
public:
PartitionAllocPCScanTestBase()
- : allocator_(PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- .star_scan_quarantine = PartitionOptions::kAllowed,
- .memory_tagging = {
- .enabled =
- base::CPU::GetInstanceNoAllocation().has_mte()
- ? partition_alloc::PartitionOptions::kEnabled
- : partition_alloc::PartitionOptions::kDisabled}}) {
+ : allocator_([]() {
+ PartitionOptions opts;
+ opts.aligned_alloc = PartitionOptions::kAllowed;
+ opts.star_scan_quarantine = PartitionOptions::kAllowed;
+ opts.memory_tagging = {
+ .enabled = base::CPU::GetInstanceNoAllocation().has_mte()
+ ? partition_alloc::PartitionOptions::kEnabled
+ : partition_alloc::PartitionOptions::kDisabled};
+ return opts;
+ }()) {
PartitionAllocGlobalInit([](size_t) { PA_LOG(FATAL) << "Out of memory"; });
// Previous test runs within the same process decommit pools, therefore
// we need to make sure that the card table is recommitted for each run.
@@ -206,6 +208,12 @@
static void Destroy(PartitionRoot& root, List* list) { root.Free(list); }
};
+constexpr auto kPartitionOptionWithStarScan = []() {
+ PartitionOptions opts;
+ opts.star_scan_quarantine = PartitionOptions::kAllowed;
+ return opts;
+}();
+
TEST_F(PartitionAllocPCScanTest, ArbitraryObjectInQuarantine) {
using ListType = List<8>;
@@ -459,13 +467,9 @@
using SourceList = List<64>;
using ValueList = SourceList;
- PartitionRoot source_root(PartitionOptions{
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ PartitionRoot source_root(kPartitionOptionWithStarScan);
source_root.UncapEmptySlotSpanMemoryForTesting();
- PartitionRoot value_root(PartitionOptions{
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ PartitionRoot value_root(kPartitionOptionWithStarScan);
value_root.UncapEmptySlotSpanMemoryForTesting();
PCScan::RegisterScannableRoot(&source_root);
@@ -484,13 +488,9 @@
using SourceList = List<64>;
using ValueList = SourceList;
- PartitionRoot source_root(PartitionOptions{
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ PartitionRoot source_root(kPartitionOptionWithStarScan);
source_root.UncapEmptySlotSpanMemoryForTesting();
- PartitionRoot value_root(PartitionOptions{
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ PartitionRoot value_root(kPartitionOptionWithStarScan);
value_root.UncapEmptySlotSpanMemoryForTesting();
PCScan::RegisterScannableRoot(&source_root);
@@ -509,13 +509,9 @@
using SourceList = List<64>;
using ValueList = SourceList;
- PartitionRoot source_root(PartitionOptions{
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ PartitionRoot source_root(kPartitionOptionWithStarScan);
source_root.UncapEmptySlotSpanMemoryForTesting();
- PartitionRoot value_root(PartitionOptions{
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ PartitionRoot value_root(kPartitionOptionWithStarScan);
value_root.UncapEmptySlotSpanMemoryForTesting();
PCScan::RegisterNonScannableRoot(&source_root);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap.h b/base/allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap.h
index c3201d1..3f7fa1b 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap.h
+++ b/base/allocator/partition_allocator/src/partition_alloc/starscan/state_bitmap.h
@@ -63,13 +63,13 @@
kQuarantined1 = 0b01,
kQuarantined2 = 0b10,
kAlloced = 0b11,
- kNumOfStates = 4,
+ kMaxValue = kAlloced,
};
using CellType = uintptr_t;
static constexpr size_t kBitsPerCell = sizeof(CellType) * CHAR_BIT;
static constexpr size_t kBitsNeededForAllocation =
- base::bits::Log2Floor(static_cast<size_t>(State::kNumOfStates));
+ std::bit_width(static_cast<uint8_t>(State::kMaxValue));
static constexpr CellType kStateMask = (1 << kBitsNeededForAllocation) - 1;
static constexpr size_t kBitmapSize =
diff --git a/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.cc b/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.cc
index d86e15d..27d32c8 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/starscan/write_protector.cc
@@ -42,7 +42,11 @@
while (true) {
// Pool on the uffd descriptor for page fault events.
- pollfd pollfd{.fd = uffd, .events = POLLIN};
+ pollfd pollfd{
+ .fd = uffd,
+ .events = POLLIN,
+ .revents = 0, // Unused output param of `pool` call.
+ };
const int nready = PA_HANDLE_EINTR(poll(&pollfd, 1, -1));
PA_CHECK(-1 != nready);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/thread_cache_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/thread_cache_unittest.cc
index 83cdaa7..cee8e29 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/thread_cache_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/thread_cache_unittest.cc
@@ -60,14 +60,14 @@
// Forbid extras, since they make finding out which bucket is used harder.
std::unique_ptr<PartitionAllocatorForTesting> CreateAllocator() {
- std::unique_ptr<PartitionAllocatorForTesting> allocator =
- std::make_unique<PartitionAllocatorForTesting>(PartitionOptions {
- .aligned_alloc = PartitionOptions::kAllowed,
+ PartitionOptions opts;
+ opts.aligned_alloc = PartitionOptions::kAllowed;
#if !BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
- .thread_cache = PartitionOptions::kEnabled,
+ opts.thread_cache = PartitionOptions::kEnabled;
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ opts.star_scan_quarantine = PartitionOptions::kAllowed;
+ std::unique_ptr<PartitionAllocatorForTesting> allocator =
+ std::make_unique<PartitionAllocatorForTesting>(opts);
allocator->root()->UncapEmptySlotSpanMemoryForTesting();
return allocator;
@@ -274,10 +274,10 @@
}
TEST_P(PartitionAllocThreadCacheTest, NoCrossPartitionCache) {
- PartitionAllocatorForTesting allocator(PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- .star_scan_quarantine = PartitionOptions::kAllowed,
- });
+ PartitionOptions opts;
+ opts.aligned_alloc = PartitionOptions::kAllowed;
+ opts.star_scan_quarantine = PartitionOptions::kAllowed;
+ PartitionAllocatorForTesting allocator(opts);
size_t bucket_index = FillThreadCacheAndReturnIndex(kSmallSize);
void* ptr = allocator.root()->Alloc(
diff --git a/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey_unittest.cc b/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey_unittest.cc
index 7869596..7e9ec5c 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey_unittest.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/pkey_unittest.cc
@@ -111,10 +111,12 @@
}
isolated_globals.pkey = pkey;
- isolated_globals.allocator->init(PartitionOptions{
- .aligned_alloc = PartitionOptions::kAllowed,
- .thread_isolation = ThreadIsolationOption(isolated_globals.pkey),
- });
+ isolated_globals.allocator->init([]() {
+ partition_alloc::PartitionOptions opts;
+ opts.aligned_alloc = PartitionOptions::kAllowed;
+ opts.thread_isolation = ThreadIsolationOption(isolated_globals.pkey);
+ return opts;
+ }());
InitializeIsolatedThread();
diff --git a/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.cc b/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.cc
index 55491f7..6b83265 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/thread_isolation/thread_isolation.cc
@@ -7,6 +7,7 @@
#if BUILDFLAG(ENABLE_THREAD_ISOLATION)
#include "partition_alloc/address_pool_manager.h"
+#include "partition_alloc/page_allocator.h"
#include "partition_alloc/partition_alloc_check.h"
#include "partition_alloc/partition_alloc_constants.h"
#include "partition_alloc/reservation_offset_table.h"
@@ -23,9 +24,19 @@
void WriteProtectThreadIsolatedMemory(ThreadIsolationOption thread_isolation,
void* address,
- size_t size) {
+ size_t size,
+ bool read_only = false) {
PA_DCHECK((reinterpret_cast<uintptr_t>(address) &
PA_THREAD_ISOLATED_ALIGN_OFFSET_MASK) == 0);
+ if (read_only) {
+ SetSystemPagesAccess(
+ address, size,
+ PageAccessibilityConfiguration(
+ thread_isolation.enabled
+ ? PageAccessibilityConfiguration::Permissions::kRead
+ : PageAccessibilityConfiguration::Permissions::kReadWrite));
+ return;
+ }
#if BUILDFLAG(ENABLE_PKEYS)
partition_alloc::internal::TagMemoryWithPkey(
thread_isolation.enabled ? thread_isolation.pkey : kDefaultPkey, address,
@@ -38,9 +49,10 @@
template <typename T>
void WriteProtectThreadIsolatedVariable(ThreadIsolationOption thread_isolation,
T& var,
- size_t offset = 0) {
+ size_t offset = 0,
+ bool read_only = false) {
WriteProtectThreadIsolatedMemory(thread_isolation, (char*)&var + offset,
- sizeof(T) - offset);
+ sizeof(T) - offset, read_only);
}
int MprotectWithThreadIsolation(void* addr,
@@ -54,7 +66,7 @@
void WriteProtectThreadIsolatedGlobals(ThreadIsolationOption thread_isolation) {
WriteProtectThreadIsolatedVariable(thread_isolation,
- PartitionAddressSpace::setup_);
+ PartitionAddressSpace::setup_, 0, true);
AddressPoolManager::Pool* pool =
AddressPoolManager::GetInstance().GetPool(kThreadIsolatedPoolHandle);
diff --git a/base/android/base_feature_map.cc b/base/android/base_feature_map.cc
index 1233215..e6320e5 100644
--- a/base/android/base_feature_map.cc
+++ b/base/android/base_feature_map.cc
@@ -15,8 +15,6 @@
// this array refer to features defined in base_features.h.
const base::Feature* const kFeaturesExposedToJava[] = {
&features::kBrowserProcessMemoryPurge,
- &features::kCrashBrowserOnChildMismatchIfBrowserChanged,
- &features::kCrashBrowserOnAnyChildMismatch,
}; // namespace
// static
diff --git a/base/android/base_features.cc b/base/android/base_features.cc
index 3254c5b..fc5db50 100644
--- a/base/android/base_features.cc
+++ b/base/android/base_features.cc
@@ -16,19 +16,4 @@
"BrowserProcessMemoryPurge",
FEATURE_ENABLED_BY_DEFAULT);
-// Crash the browser process if a child process is created which does not match
-// the browser process and the browser package appears to have changed since the
-// browser process was launched, so that the browser process will be started
-// fresh when next used, hopefully resolving the issue.
-BASE_FEATURE(kCrashBrowserOnChildMismatchIfBrowserChanged,
- "CrashBrowserOnChildMismatchIfBrowserChanged",
- FEATURE_ENABLED_BY_DEFAULT);
-
-// Crash the browser process if a child process is created which does not match
-// the browser process regardless of whether the browser package appears to have
-// changed.
-BASE_FEATURE(kCrashBrowserOnAnyChildMismatch,
- "CrashBrowserOnAnyChildMismatch",
- FEATURE_DISABLED_BY_DEFAULT);
-
} // namespace base::android::features
diff --git a/base/android/base_features.h b/base/android/base_features.h
index f49a9f6..723470b 100644
--- a/base/android/base_features.h
+++ b/base/android/base_features.h
@@ -14,8 +14,6 @@
// Alphabetical:
BASE_DECLARE_FEATURE(kBrowserProcessMemoryPurge);
-BASE_DECLARE_FEATURE(kCrashBrowserOnChildMismatchIfBrowserChanged);
-BASE_DECLARE_FEATURE(kCrashBrowserOnAnyChildMismatch);
} // namespace base::android::features
diff --git a/base/android/field_trial_list.cc b/base/android/field_trial_list.cc
index 5f29475..8156b7d 100644
--- a/base/android/field_trial_list.cc
+++ b/base/android/field_trial_list.cc
@@ -29,9 +29,9 @@
TrialLogger(const TrialLogger&) = delete;
TrialLogger& operator=(const TrialLogger&) = delete;
- void OnFieldTrialGroupFinalized(const std::string& trial_name,
+ void OnFieldTrialGroupFinalized(const base::FieldTrial& trial,
const std::string& group_name) override {
- Log(trial_name, group_name);
+ Log(trial.trial_name(), group_name);
}
static void Log(const std::string& trial_name,
diff --git a/base/android/jank_metric_uma_recorder.cc b/base/android/jank_metric_uma_recorder.cc
index bca271e..5fce95a 100644
--- a/base/android/jank_metric_uma_recorder.cc
+++ b/base/android/jank_metric_uma_recorder.cc
@@ -12,34 +12,139 @@
#include "base/metrics/histogram_functions.h"
#include "base/time/time.h"
#include "base/trace_event/base_tracing.h"
+#include "jank_metric_uma_recorder.h"
namespace base::android {
namespace {
-void RecordJankMetricReportingIntervalTraceEvent(
- int64_t reporting_interval_start_time,
- int64_t reporting_interval_duration,
- uint64_t janky_frame_count,
- uint64_t non_janky_frame_count,
- int scenario) {
- if (reporting_interval_start_time <= 0) {
- return;
+// Histogram min, max and no. of buckets.
+constexpr int kVsyncCountsMin = 1;
+constexpr int kVsyncCountsMax = 50;
+constexpr int kVsyncCountsBuckets = 25;
+
+enum class PerScrollHistogramType {
+ kPercentage = 0,
+ kMax = 1,
+ kSum = 2,
+};
+
+const char* GetPerScrollHistogramName(JankScenario scenario,
+ int num_frames,
+ PerScrollHistogramType type) {
+#define HISTOGRAM_NAME(hist_scenario, hist_type, length) \
+ "Android.FrameTimelineJank." #hist_scenario "." #hist_type \
+ "." \
+ "PerScroll." #length
+ if (scenario == JankScenario::WEBVIEW_SCROLLING) {
+ if (type == PerScrollHistogramType::kPercentage) {
+ if (num_frames <= 16) {
+ return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage, Small);
+ } else if (num_frames <= 64) {
+ return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage,
+ Medium);
+ } else {
+ return HISTOGRAM_NAME(WebviewScrolling, DelayedFramesPercentage, Large);
+ }
+ } else if (type == PerScrollHistogramType::kMax) {
+ if (num_frames <= 16) {
+ return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, Small);
+ } else if (num_frames <= 64) {
+ return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, Medium);
+ } else {
+ return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsMax, Large);
+ }
+ } else {
+ DCHECK_EQ(type, PerScrollHistogramType::kSum);
+ if (num_frames <= 16) {
+ return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, Small);
+ } else if (num_frames <= 64) {
+ return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, Medium);
+ } else {
+ return HISTOGRAM_NAME(WebviewScrolling, MissedVsyncsSum, Large);
+ }
+ }
+ } else {
+ DCHECK_EQ(scenario, JankScenario::FEED_SCROLLING);
+ if (type == PerScrollHistogramType::kPercentage) {
+ if (num_frames <= 16) {
+ return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, Small);
+ } else if (num_frames <= 64) {
+ return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, Medium);
+ } else {
+ return HISTOGRAM_NAME(FeedScrolling, DelayedFramesPercentage, Large);
+ }
+ } else if (type == PerScrollHistogramType::kMax) {
+ if (num_frames <= 16) {
+ return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, Small);
+ } else if (num_frames <= 64) {
+ return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, Medium);
+ } else {
+ return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsMax, Large);
+ }
+ } else {
+ DCHECK_EQ(type, PerScrollHistogramType::kSum);
+ if (num_frames <= 16) {
+ return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, Small);
+ } else if (num_frames <= 64) {
+ return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, Medium);
+ } else {
+ return HISTOGRAM_NAME(FeedScrolling, MissedVsyncsSum, Large);
+ }
+ }
+ }
+#undef HISTOGRAM_NAME
+}
+
+// Emits trace event for all scenarios and per scroll histograms for webview and
+// feed scrolling scenarios.
+void EmitMetrics(JankScenario scenario,
+ int janky_frame_count,
+ int missed_vsyncs_max,
+ int missed_vsyncs_sum,
+ int num_presented_frames,
+ int64_t reporting_interval_start_time,
+ int64_t reporting_interval_duration) {
+ DCHECK_GT(num_presented_frames, 0);
+ int delayed_frames_percentage =
+ (100 * janky_frame_count) / num_presented_frames;
+ if (reporting_interval_start_time > 0) {
+ // The following code does nothing if base tracing is disabled.
+ [[maybe_unused]] int non_janky_frame_count =
+ num_presented_frames - janky_frame_count;
+ [[maybe_unused]] auto t = perfetto::Track(static_cast<uint64_t>(
+ reporting_interval_start_time + static_cast<int>(scenario)));
+ TRACE_EVENT_BEGIN(
+ "android_webview.timeline,android.ui.jank",
+ "JankMetricsReportingInterval", t,
+ base::TimeTicks::FromUptimeMillis(reporting_interval_start_time),
+ "janky_frames", janky_frame_count, "non_janky_frames",
+ non_janky_frame_count, "scenario", static_cast<int>(scenario),
+ "delayed_frames_percentage", delayed_frames_percentage,
+ "missed_vsyns_max", missed_vsyncs_max, "missed_vsyncs_sum",
+ missed_vsyncs_sum);
+ TRACE_EVENT_END(
+ "android_webview.timeline,android.ui.jank", t,
+ base::TimeTicks::FromUptimeMillis(
+ (reporting_interval_start_time + reporting_interval_duration)));
}
- // The following code does nothing if base tracing is disabled.
- [[maybe_unused]] auto t = perfetto::Track(
- static_cast<uint64_t>(reporting_interval_start_time + scenario));
- TRACE_EVENT_BEGIN(
- "android_webview.timeline,android.ui.jank",
- "JankMetricsReportingInterval", t,
- base::TimeTicks::FromUptimeMillis(reporting_interval_start_time),
- "janky_frames", janky_frame_count, "non_janky_frames",
- non_janky_frame_count, "scenario", scenario);
- TRACE_EVENT_END(
- "android_webview.timeline,android.ui.jank", t,
- base::TimeTicks::FromUptimeMillis(
- (reporting_interval_start_time + reporting_interval_duration)));
+ if (scenario != JankScenario::WEBVIEW_SCROLLING &&
+ scenario != JankScenario::FEED_SCROLLING) {
+ return;
+ }
+ base::UmaHistogramPercentage(
+ GetPerScrollHistogramName(scenario, num_presented_frames,
+ PerScrollHistogramType::kPercentage),
+ delayed_frames_percentage);
+ base::UmaHistogramCustomCounts(
+ GetPerScrollHistogramName(scenario, num_presented_frames,
+ PerScrollHistogramType::kMax),
+ missed_vsyncs_max, kVsyncCountsMin, kVsyncCountsMax, kVsyncCountsBuckets);
+ base::UmaHistogramCustomCounts(
+ GetPerScrollHistogramName(scenario, num_presented_frames,
+ PerScrollHistogramType::kSum),
+ missed_vsyncs_sum, kVsyncCountsMin, kVsyncCountsMax, kVsyncCountsBuckets);
}
} // namespace
@@ -144,10 +249,18 @@
base::Nanoseconds(frame_duration_ns));
}
- uint64_t janky_frame_count = 0;
+ int janky_frame_count = 0;
+ int missed_vsyncs_max = 0;
+ int missed_vsyncs_sum = 0;
+ const int num_presented_frames = static_cast<int>(missed_vsyncs.size());
for (int curr_frame_missed_vsyncs : missed_vsyncs) {
bool is_janky = curr_frame_missed_vsyncs > 0;
+ if (curr_frame_missed_vsyncs > missed_vsyncs_max) {
+ missed_vsyncs_max = curr_frame_missed_vsyncs;
+ }
+ missed_vsyncs_sum += curr_frame_missed_vsyncs;
+
base::UmaHistogramEnumeration(
janky_frames_per_scenario_histogram_name,
is_janky ? FrameJankStatus::kJanky : FrameJankStatus::kNonJanky);
@@ -156,10 +269,12 @@
}
}
- RecordJankMetricReportingIntervalTraceEvent(
- java_reporting_interval_start_time, java_reporting_interval_duration,
- janky_frame_count, missed_vsyncs.size() - janky_frame_count,
- java_scenario_enum);
+ if (num_presented_frames > 0) {
+ EmitMetrics(scenario, janky_frame_count, missed_vsyncs_max,
+ missed_vsyncs_sum, num_presented_frames,
+ java_reporting_interval_start_time,
+ java_reporting_interval_duration);
+ }
}
} // namespace base::android
diff --git a/base/android/jank_metric_uma_recorder_unittest.cc b/base/android/jank_metric_uma_recorder_unittest.cc
index 4659d4a..deb263d 100644
--- a/base/android/jank_metric_uma_recorder_unittest.cc
+++ b/base/android/jank_metric_uma_recorder_unittest.cc
@@ -8,12 +8,14 @@
#include <cstddef>
#include <cstdint>
+#include <vector>
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/metrics/histogram.h"
#include "base/test/metrics/histogram_tester.h"
+#include "jank_metric_uma_recorder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -60,6 +62,13 @@
};
const size_t kMissedVsyncsLen = kDurationsLen;
+struct ScrollTestCase {
+ JankScenario scenario;
+ std::string test_name;
+ int num_frames;
+ std::string suffix;
+};
+
} // namespace
TEST(JankMetricUMARecorder, TestUMARecording) {
@@ -79,6 +88,10 @@
HistogramTester complete_histogram_tester;
size_t total_histograms = 0;
for (int i = kMinScenario; i < kMaxScenario; ++i) {
+ if ((i == static_cast<int>(JankScenario::WEBVIEW_SCROLLING)) ||
+ (i == static_cast<int>(JankScenario::FEED_SCROLLING))) {
+ continue;
+ }
// HistogramTester takes a snapshot of currently incremented counters so
// everything is scoped to just this iteration of the for loop.
HistogramTester histogram_tester;
@@ -123,4 +136,90 @@
<< kJankyName;
}
}
+
+class JankMetricUMARecorderPerScrollTests
+ : public testing::Test,
+ public testing::WithParamInterface<ScrollTestCase> {};
+INSTANTIATE_TEST_SUITE_P(
+ JankMetricUMARecorderPerScrollTests,
+ JankMetricUMARecorderPerScrollTests,
+ testing::ValuesIn<ScrollTestCase>({
+ {JankScenario::WEBVIEW_SCROLLING, "EmitsSmallScrollHistogramInWebview",
+ 10, "Small"},
+ {JankScenario::WEBVIEW_SCROLLING, "EmitsMediumScrollHistogramInWebview",
+ 50, "Medium"},
+ {JankScenario::WEBVIEW_SCROLLING, "EmitsLargeScrollHistogramInWebview",
+ 65, "Large"},
+ {JankScenario::FEED_SCROLLING, "EmitsSmallScrollHistogramInFeed", 10,
+ "Small"},
+ {JankScenario::FEED_SCROLLING, "EmitsMediumScrollHistogramInFeed", 50,
+ "Medium"},
+ {JankScenario::FEED_SCROLLING, "EmitsLargeScrollHistogramInFeed", 65,
+ "Large"},
+ }),
+ [](const testing::TestParamInfo<
+ JankMetricUMARecorderPerScrollTests::ParamType>& info) {
+ return info.param.test_name;
+ });
+
+TEST_P(JankMetricUMARecorderPerScrollTests, EmitsPerScrollHistograms) {
+ const ScrollTestCase& params = GetParam();
+
+ JNIEnv* env = AttachCurrentThread();
+ HistogramTester histogram_tester;
+ std::vector<int64_t> durations = {1000000L, 1000000L, 1000000L};
+ std::vector<int> missed_vsyncs = {0, 3, 1};
+ const int expected_janky_frames = 2;
+ const int expected_vsyncs_max = 3;
+ const int expected_vsyncs_sum = 4;
+
+ for (int i = durations.size(); i < params.num_frames; i++) {
+ durations.push_back(1000000L);
+ missed_vsyncs.push_back(0);
+ }
+
+ jlongArray java_durations =
+ GenerateJavaLongArray(env, durations.data(), durations.size());
+ jintArray java_missed_vsyncs =
+ GenerateJavaIntArray(env, missed_vsyncs.data(), missed_vsyncs.size());
+
+ RecordJankMetrics(
+ env, base::android::JavaParamRef<jlongArray>(env, java_durations),
+ base::android::JavaParamRef<jintArray>(env, java_missed_vsyncs),
+ /* java_reporting_interval_start_time = */ 0,
+ /* java_reporting_interval_duration = */ 1000,
+ static_cast<int>(params.scenario));
+
+ int expected_delayed_frames_percentage =
+ (100 * expected_janky_frames) / params.num_frames;
+ std::string scenario_name = "";
+ if (params.scenario == JankScenario::WEBVIEW_SCROLLING) {
+ scenario_name = "WebviewScrolling";
+ } else {
+ DCHECK_EQ(params.scenario, JankScenario::FEED_SCROLLING);
+ scenario_name = "FeedScrolling";
+ }
+ std::string delayed_frames_histogram = "Android.FrameTimelineJank." +
+ scenario_name +
+ ".DelayedFramesPercentage."
+ "PerScroll." +
+ params.suffix;
+ std::string missed_vsyncs_max_histogram = "Android.FrameTimelineJank." +
+ scenario_name +
+ ".MissedVsyncsMax."
+ "PerScroll." +
+ params.suffix;
+ std::string missed_vsyncs_sum_histogram = "Android.FrameTimelineJank." +
+ scenario_name +
+ ".MissedVsyncsSum."
+ "PerScroll." +
+ params.suffix;
+ histogram_tester.ExpectUniqueSample(delayed_frames_histogram,
+ expected_delayed_frames_percentage, 1);
+ histogram_tester.ExpectUniqueSample(missed_vsyncs_max_histogram,
+ expected_vsyncs_max, 1);
+ histogram_tester.ExpectUniqueSample(missed_vsyncs_sum_histogram,
+ expected_vsyncs_sum, 1);
+}
+
} // namespace base::android
diff --git a/base/android/java/src/org/chromium/base/ActivityState.java b/base/android/java/src/org/chromium/base/ActivityState.java
index 70ebf9b..08adc88 100644
--- a/base/android/java/src/org/chromium/base/ActivityState.java
+++ b/base/android/java/src/org/chromium/base/ActivityState.java
@@ -9,40 +9,34 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-/**
- * A set of states that represent the last state change of an Activity.
- */
+/** A set of states that represent the last state change of an Activity. */
@Retention(RetentionPolicy.SOURCE)
-@IntDef({ActivityState.CREATED, ActivityState.STARTED, ActivityState.RESUMED, ActivityState.PAUSED,
- ActivityState.STOPPED, ActivityState.DESTROYED})
+@IntDef({
+ ActivityState.CREATED,
+ ActivityState.STARTED,
+ ActivityState.RESUMED,
+ ActivityState.PAUSED,
+ ActivityState.STOPPED,
+ ActivityState.DESTROYED
+})
public @interface ActivityState {
- /**
- * Represents Activity#onCreate().
- */
+ /** Represents Activity#onCreate(). */
int CREATED = 1;
- /**
- * Represents Activity#onStart().
- */
+ /** Represents Activity#onStart(). */
int STARTED = 2;
- /**
- * Represents Activity#onResume().
- */
+ /** Represents Activity#onResume(). */
int RESUMED = 3;
- /**
- * Represents Activity#onPause().
- */
+ /** Represents Activity#onPause(). */
int PAUSED = 4;
- /**
- * Represents Activity#onStop().
- */
+ /** Represents Activity#onStop(). */
int STOPPED = 5;
/**
- * Represents Activity#onDestroy(). This is also used when the state of an Activity is unknown.
+ * Represents Activity#onDestroy(). This is also used when the state of an Activity is unknown.
*/
int DESTROYED = 6;
}
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
index 753b8e4..33bfc1d 100644
--- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
+++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -29,9 +29,11 @@
import android.view.View;
import android.view.textclassifier.TextClassifier;
import android.widget.TextView;
+
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -48,8 +50,7 @@
public class ApiCompatibilityUtils {
private static final String TAG = "ApiCompatUtil";
- private ApiCompatibilityUtils() {
- }
+ private ApiCompatibilityUtils() {}
@RequiresApi(Build.VERSION_CODES.Q)
private static class ApisQ {
@@ -68,7 +69,9 @@
(ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
for (Display display : displays) {
if (display.getState() == Display.STATE_ON
- && am.isActivityStartAllowedOnDisplay(activity, display.getDisplayId(),
+ && am.isActivityStartAllowedOnDisplay(
+ activity,
+ display.getDisplayId(),
new Intent(activity, activity.getClass()))) {
displayList.add(display.getDisplayId());
}
@@ -111,8 +114,9 @@
private static class ApisNMR1 {
static boolean isDemoUser() {
UserManager userManager =
- (UserManager) ContextUtils.getApplicationContext().getSystemService(
- Context.USER_SERVICE);
+ (UserManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.USER_SERVICE);
return userManager.isDemoUser();
}
}
@@ -315,10 +319,17 @@
float offsetRight =
(float) View.class.getMethod("getHandwritingBoundsOffsetRight").invoke(view);
// this.setHandwritingBoundsOffsets(offsetLeft, offsetTop, offsetRight, 0);
- Method setHandwritingBoundsOffsets = View.class.getMethod("setHandwritingBoundsOffsets",
- float.class, float.class, float.class, float.class);
+ Method setHandwritingBoundsOffsets =
+ View.class.getMethod(
+ "setHandwritingBoundsOffsets",
+ float.class,
+ float.class,
+ float.class,
+ float.class);
setHandwritingBoundsOffsets.invoke(view, offsetLeft, offsetTop, offsetRight, 0);
- } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException
+ } catch (IllegalAccessException
+ | InvocationTargetException
+ | NoSuchMethodException
| NullPointerException e) {
// Do nothing.
}
@@ -347,9 +358,7 @@
return false;
}
- /**
- * Retrieves an image for the given uri as a Bitmap.
- */
+ /** Retrieves an image for the given uri as a Bitmap. */
public static Bitmap getBitmapByUri(ContentResolver cr, Uri uri) throws IOException {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
return ApisP.getBitmapByUri(cr, uri);
diff --git a/base/android/java/src/org/chromium/base/ApkAssets.java b/base/android/java/src/org/chromium/base/ApkAssets.java
index 5f9577c..76b711a 100644
--- a/base/android/java/src/org/chromium/base/ApkAssets.java
+++ b/base/android/java/src/org/chromium/base/ApkAssets.java
@@ -38,8 +38,9 @@
}
AssetManager manager = context.getAssets();
afd = manager.openNonAssetFd(fileName);
- return new long[] {afd.getParcelFileDescriptor().detachFd(), afd.getStartOffset(),
- afd.getLength()};
+ return new long[] {
+ afd.getParcelFileDescriptor().detachFd(), afd.getStartOffset(), afd.getLength()
+ };
} catch (IOException e) {
sLastError = "Error while loading asset " + fileName + " from " + splitName + ": " + e;
// As a general rule there's no point logging here because the caller should handle
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java
index bff2410..2b5c3c5 100644
--- a/base/android/java/src/org/chromium/base/ApplicationStatus.java
+++ b/base/android/java/src/org/chromium/base/ApplicationStatus.java
@@ -75,15 +75,11 @@
}
}
- /**
- * A map of which observers listen to state changes from which {@link Activity}.
- */
+ /** A map of which observers listen to state changes from which {@link Activity}. */
private static final Map<Activity, ActivityInfo> sActivityInfo =
Collections.synchronizedMap(new HashMap<Activity, ActivityInfo>());
- /**
- * A map to cache TaskId for each {@link Activity}.
- */
+ /** A map to cache TaskId for each {@link Activity}. */
public static final Map<Activity, Integer> sActivityTaskId =
Collections.synchronizedMap(new HashMap<Activity, Integer>());
@@ -97,20 +93,14 @@
// when no activity has been observed.
private static int sCurrentApplicationState = ApplicationState.UNKNOWN;
- /**
- * Last activity that was shown (or null if none or it was destroyed).
- */
+ /** Last activity that was shown (or null if none or it was destroyed). */
@SuppressLint("StaticFieldLeak")
private static Activity sActivity;
- /**
- * A lazily initialized listener that forwards application state changes to native.
- */
+ /** A lazily initialized listener that forwards application state changes to native. */
private static ApplicationStateListener sNativeApplicationStateListener;
- /**
- * A list of observers to be notified when any {@link Activity} has a state change.
- */
+ /** A list of observers to be notified when any {@link Activity} has a state change. */
private static ObserverList<ActivityStateListener> sGeneralActivityStateListeners;
/**
@@ -125,14 +115,10 @@
*/
private static ObserverList<WindowFocusChangedListener> sWindowFocusListeners;
- /**
- * A list of observers to be notified when the visibility of any task changes.
- */
+ /** A list of observers to be notified when the visibility of any task changes. */
private static ObserverList<TaskVisibilityListener> sTaskVisibilityListeners;
- /**
- * Interface to be implemented by listeners.
- */
+ /** Interface to be implemented by listeners. */
public interface ApplicationStateListener {
/**
* Called when the application's state changes.
@@ -142,9 +128,7 @@
void onApplicationStateChange(@ApplicationState int newState);
}
- /**
- * Interface to be implemented by listeners.
- */
+ /** Interface to be implemented by listeners. */
public interface ActivityStateListener {
/**
* Called when the activity's state changes.
@@ -155,9 +139,7 @@
void onActivityStateChange(Activity activity, @ActivityState int newState);
}
- /**
- * Interface to be implemented by listeners for window focus events.
- */
+ /** Interface to be implemented by listeners for window focus events. */
public interface WindowFocusChangedListener {
/**
* Called when the window focus changes for {@code activity}.
@@ -168,9 +150,7 @@
public void onWindowFocusChanged(Activity activity, boolean hasFocus);
}
- /**
- * Interface to be implemented by listeners for task visibility changes.
- */
+ /** Interface to be implemented by listeners for task visibility changes. */
public interface TaskVisibilityListener {
/**
* Called when the visibility of a task changes.
@@ -236,8 +216,8 @@
public static boolean isCachingEnabled() {
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
- return ContextUtils.getAppSharedPreferences().getBoolean(
- CACHE_ACTIVITY_TASKID_KEY, false);
+ return ContextUtils.getAppSharedPreferences()
+ .getBoolean(CACHE_ACTIVITY_TASKID_KEY, false);
}
}
@@ -271,7 +251,8 @@
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- if (method.getName().equals("onWindowFocusChanged") && args.length == 1
+ if (method.getName().equals("onWindowFocusChanged")
+ && args.length == 1
&& args[0] instanceof Boolean) {
onWindowFocusChanged((boolean) args[0]);
return null;
@@ -322,77 +303,83 @@
sCurrentApplicationState = ApplicationState.HAS_DESTROYED_ACTIVITIES;
}
- registerWindowFocusChangedListener(new WindowFocusChangedListener() {
- @Override
- public void onWindowFocusChanged(Activity activity, boolean hasFocus) {
- if (!hasFocus || activity == sActivity) return;
+ registerWindowFocusChangedListener(
+ new WindowFocusChangedListener() {
+ @Override
+ public void onWindowFocusChanged(Activity activity, boolean hasFocus) {
+ if (!hasFocus || activity == sActivity) return;
- int state = getStateForActivity(activity);
+ int state = getStateForActivity(activity);
- if (state != ActivityState.DESTROYED && state != ActivityState.STOPPED) {
- sActivity = activity;
- }
+ if (state != ActivityState.DESTROYED && state != ActivityState.STOPPED) {
+ sActivity = activity;
+ }
- // TODO(dtrainor): Notify of active activity change?
- }
- });
+ // TODO(dtrainor): Notify of active activity change?
+ }
+ });
- application.registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() {
- @Override
- public void onActivityCreated(final Activity activity, Bundle savedInstanceState) {
- onStateChange(activity, ActivityState.CREATED);
- Window.Callback callback = activity.getWindow().getCallback();
- activity.getWindow().setCallback(createWindowCallbackProxy(activity, callback));
- }
+ application.registerActivityLifecycleCallbacks(
+ new ActivityLifecycleCallbacks() {
+ @Override
+ public void onActivityCreated(
+ final Activity activity, Bundle savedInstanceState) {
+ onStateChange(activity, ActivityState.CREATED);
+ Window.Callback callback = activity.getWindow().getCallback();
+ activity.getWindow()
+ .setCallback(createWindowCallbackProxy(activity, callback));
+ }
- @Override
- public void onActivityDestroyed(Activity activity) {
- onStateChange(activity, ActivityState.DESTROYED);
- checkCallback(activity);
- }
+ @Override
+ public void onActivityDestroyed(Activity activity) {
+ onStateChange(activity, ActivityState.DESTROYED);
+ checkCallback(activity);
+ }
- @Override
- public void onActivityPaused(Activity activity) {
- onStateChange(activity, ActivityState.PAUSED);
- checkCallback(activity);
- }
+ @Override
+ public void onActivityPaused(Activity activity) {
+ onStateChange(activity, ActivityState.PAUSED);
+ checkCallback(activity);
+ }
- @Override
- public void onActivityResumed(Activity activity) {
- onStateChange(activity, ActivityState.RESUMED);
- checkCallback(activity);
- }
+ @Override
+ public void onActivityResumed(Activity activity) {
+ onStateChange(activity, ActivityState.RESUMED);
+ checkCallback(activity);
+ }
- @Override
- public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
- checkCallback(activity);
- }
+ @Override
+ public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
+ checkCallback(activity);
+ }
- @Override
- public void onActivityStarted(Activity activity) {
- onStateChange(activity, ActivityState.STARTED);
- checkCallback(activity);
- }
+ @Override
+ public void onActivityStarted(Activity activity) {
+ onStateChange(activity, ActivityState.STARTED);
+ checkCallback(activity);
+ }
- @Override
- public void onActivityStopped(Activity activity) {
- onStateChange(activity, ActivityState.STOPPED);
- checkCallback(activity);
- }
+ @Override
+ public void onActivityStopped(Activity activity) {
+ onStateChange(activity, ActivityState.STOPPED);
+ checkCallback(activity);
+ }
- private void checkCallback(Activity activity) {
- if (BuildConfig.ENABLE_ASSERTS) {
- assert reachesWindowCallback(activity.getWindow().getCallback());
- }
- }
- });
+ private void checkCallback(Activity activity) {
+ if (BuildConfig.ENABLE_ASSERTS) {
+ assert reachesWindowCallback(activity.getWindow().getCallback());
+ }
+ }
+ });
}
@VisibleForTesting
static Window.Callback createWindowCallbackProxy(Activity activity, Window.Callback callback) {
- return (Window.Callback) Proxy.newProxyInstance(Window.Callback.class.getClassLoader(),
- new Class[] {Window.Callback.class},
- new ApplicationStatus.WindowCallbackProxy(activity, callback));
+ return (Window.Callback)
+ Proxy.newProxyInstance(
+ Window.Callback.class.getClassLoader(),
+ new Class[] {Window.Callback.class},
+ new ApplicationStatus.WindowCallbackProxy(activity, callback));
}
/**
@@ -413,7 +400,7 @@
}
if (Proxy.isProxyClass(callback.getClass())) {
return Proxy.getInvocationHandler(callback)
- instanceof ApplicationStatus.WindowCallbackProxy;
+ instanceof ApplicationStatus.WindowCallbackProxy;
}
for (Class<?> c = callback.getClass(); c != Object.class; c = c.getSuperclass()) {
for (Field f : c.getDeclaredFields()) {
@@ -509,9 +496,7 @@
}
}
- /**
- * Testing method to update the state of the specified activity.
- */
+ /** Testing method to update the state of the specified activity. */
@VisibleForTesting
@MainThread
public static void onStateChangeForTesting(Activity activity, int newState) {
@@ -641,8 +626,7 @@
assert isInitialized();
for (Map.Entry<Activity, ActivityInfo> entry : sActivityInfo.entrySet()) {
if (getTaskId(entry.getKey()) == taskId) {
- @ActivityState
- int state = entry.getValue().getStatus();
+ @ActivityState int state = entry.getValue().getStatus();
if (state == ActivityState.RESUMED || state == ActivityState.PAUSED) {
return true;
}
@@ -750,9 +734,7 @@
}
}
- /**
- * Mark all Activities as destroyed to avoid side-effects in future test.
- */
+ /** Mark all Activities as destroyed to avoid side-effects in future test. */
@MainThread
public static void resetActivitiesForInstrumentationTests() {
assert ThreadUtils.runningOnUiThread();
@@ -760,9 +742,9 @@
synchronized (sActivityInfo) {
// Copy the set to avoid concurrent modifications to the underlying set.
for (Activity activity : new HashSet<>(sActivityInfo.keySet())) {
- assert activity.getApplication()
- == null : "Real activities that are launched should be closed by test code "
- + "and not rely on this cleanup of mocks.";
+ assert activity.getApplication() == null
+ : "Real activities that are launched should be closed by test code "
+ + "and not rely on this cleanup of mocks.";
onStateChangeForTesting(activity, ActivityState.DESTROYED);
}
}
@@ -776,20 +758,23 @@
*/
@CalledByNative
private static void registerThreadSafeNativeApplicationStateListener() {
- ThreadUtils.runOnUiThread(new Runnable() {
- @Override
- public void run() {
- if (sNativeApplicationStateListener != null) return;
-
- sNativeApplicationStateListener = new ApplicationStateListener() {
+ ThreadUtils.runOnUiThread(
+ new Runnable() {
@Override
- public void onApplicationStateChange(int newState) {
- ApplicationStatusJni.get().onApplicationStateChange(newState);
+ public void run() {
+ if (sNativeApplicationStateListener != null) return;
+
+ sNativeApplicationStateListener =
+ new ApplicationStateListener() {
+ @Override
+ public void onApplicationStateChange(int newState) {
+ ApplicationStatusJni.get()
+ .onApplicationStateChange(newState);
+ }
+ };
+ registerApplicationStateListener(sNativeApplicationStateListener);
}
- };
- registerApplicationStateListener(sNativeApplicationStateListener);
- }
- });
+ });
}
/**
@@ -810,7 +795,8 @@
for (ActivityInfo info : sActivityInfo.values()) {
int state = info.getStatus();
- if (state != ActivityState.PAUSED && state != ActivityState.STOPPED
+ if (state != ActivityState.PAUSED
+ && state != ActivityState.STOPPED
&& state != ActivityState.DESTROYED) {
return ApplicationState.HAS_RUNNING_ACTIVITIES;
} else if (state == ActivityState.PAUSED) {
diff --git a/base/android/java/src/org/chromium/base/BaseFeatureMap.java b/base/android/java/src/org/chromium/base/BaseFeatureMap.java
index 3fc1c7f..e7c4b45 100644
--- a/base/android/java/src/org/chromium/base/BaseFeatureMap.java
+++ b/base/android/java/src/org/chromium/base/BaseFeatureMap.java
@@ -7,9 +7,7 @@
import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
-/**
- * Java accessor for base::Features listed in {@link BaseFeatures}
- */
+/** Java accessor for base::Features listed in {@link BaseFeatures} */
@JNINamespace("base::android")
public final class BaseFeatureMap extends FeatureMap {
private static final BaseFeatureMap sInstance = new BaseFeatureMap();
@@ -24,9 +22,7 @@
return sInstance;
}
- /**
- * Convenience method to call {@link #isEnabledInNative(String)} statically.
- */
+ /** Convenience method to call {@link #isEnabledInNative(String)} statically. */
public static boolean isEnabled(String featureName) {
return getInstance().isEnabledInNative(featureName);
}
diff --git a/base/android/java/src/org/chromium/base/BuildInfo.java b/base/android/java/src/org/chromium/base/BuildInfo.java
index bf35102..bb333eb 100644
--- a/base/android/java/src/org/chromium/base/BuildInfo.java
+++ b/base/android/java/src/org/chromium/base/BuildInfo.java
@@ -42,41 +42,54 @@
* e.g. com.google.android.sdksandbox:com:com.example.myappwithads
*/
public final String hostPackageName;
+
/**
* The application name (e.g. "Chrome"). For WebView, this is name of the embedding app.
* In the context of the SDK Runtime, this is the name of the app that owns this particular
* instance of the SDK Runtime.
*/
public final String hostPackageLabel;
+
/**
* By default: same as versionCode. For WebView: versionCode of the embedding app.
* In the context of the SDK Runtime, this is the versionCode of the app that owns this
* particular instance of the SDK Runtime.
*/
public final long hostVersionCode;
+
/**
* The packageName of Chrome/WebView. Use application context for host app packageName.
* Same as the host information within any child process.
*/
public final String packageName;
+
/** The versionCode of the apk. */
public final long versionCode;
+
/** The versionName of Chrome/WebView. Use application context for host app versionName. */
public final String versionName;
+
/** Result of PackageManager.getInstallerPackageName(). Never null, but may be "". */
public final String installerPackageName;
+
/** The versionCode of Play Services (for crash reporting). */
public final String gmsVersionCode;
+
/** Formatted ABI string (for crash reporting). */
public final String abiString;
+
/** Truncated version of Build.FINGERPRINT (for crash reporting). */
public final String androidBuildFingerprint;
+
/** Whether or not the device has apps installed for using custom themes. */
public final String customThemes;
+
/** Product version as stored in Android resources. */
public final String resourcesVersion;
+
/** Whether we're running on Android TV or not */
public final boolean isTV;
+
/** Whether we're running on an Android Automotive OS device or not. */
public final boolean isAutomotive;
@@ -207,15 +220,19 @@
}
if (commandLine.hasSwitch(BaseSwitches.PACKAGE_VERSION_CODE)) {
- providedPackageVersionCode = Long.parseLong(
- commandLine.getSwitchValue(BaseSwitches.PACKAGE_VERSION_CODE));
+ providedPackageVersionCode =
+ Long.parseLong(
+ commandLine.getSwitchValue(BaseSwitches.PACKAGE_VERSION_CODE));
}
}
- boolean hostInformationProvided = providedHostPackageName != null
- && providedHostPackageLabel != null && providedHostVersionCode != null
- && providedPackageName != null && providedPackageVersionName != null
- && providedPackageVersionCode != null;
+ boolean hostInformationProvided =
+ providedHostPackageName != null
+ && providedHostPackageLabel != null
+ && providedHostVersionCode != null
+ && providedPackageName != null
+ && providedPackageVersionName != null
+ && providedPackageVersionCode != null;
// We want to retrieve the original package installed to verify to host package name.
// In the case of the SDK Runtime, we would like to retrieve the package name loading the
@@ -278,8 +295,10 @@
installerPackageName = nullToEmpty(pm.getInstallerPackageName(appInstalledPackageName));
PackageInfo gmsPackageInfo = PackageUtils.getPackageInfo("com.google.android.gms", 0);
- gmsVersionCode = gmsPackageInfo != null ? String.valueOf(packageVersionCode(gmsPackageInfo))
- : "gms versionCode not available.";
+ gmsVersionCode =
+ gmsPackageInfo != null
+ ? String.valueOf(packageVersionCode(gmsPackageInfo))
+ : "gms versionCode not available.";
// Substratum is a theme engine that enables users to use custom themes provided
// by theme apps. Sometimes these can cause crashs if not installed correctly.
@@ -295,8 +314,9 @@
// corrupted resources were the cause of a crash. This can happen if the app
// loads resources from the outdated package during an update
// (http://crbug.com/820591).
- currentResourcesVersion = ContextUtils.getApplicationContext().getString(
- BuildConfig.R_STRING_PRODUCT_VERSION);
+ currentResourcesVersion =
+ ContextUtils.getApplicationContext()
+ .getString(BuildConfig.R_STRING_PRODUCT_VERSION);
} catch (Exception e) {
currentResourcesVersion = "Not found";
}
@@ -306,13 +326,16 @@
abiString = TextUtils.join(", ", Build.SUPPORTED_ABIS);
// The value is truncated, as this is used for crash and UMA reporting.
- androidBuildFingerprint = Build.FINGERPRINT.substring(
- 0, Math.min(Build.FINGERPRINT.length(), MAX_FINGERPRINT_LENGTH));
+ androidBuildFingerprint =
+ Build.FINGERPRINT.substring(
+ 0, Math.min(Build.FINGERPRINT.length(), MAX_FINGERPRINT_LENGTH));
// See https://developer.android.com/training/tv/start/hardware.html#runtime-check.
UiModeManager uiModeManager = (UiModeManager) appContext.getSystemService(UI_MODE_SERVICE);
- isTV = uiModeManager != null
- && uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION;
+ isTV =
+ uiModeManager != null
+ && uiModeManager.getCurrentModeType()
+ == Configuration.UI_MODE_TYPE_TELEVISION;
boolean isAutomotive;
try {
diff --git a/base/android/java/src/org/chromium/base/BundleUtils.java b/base/android/java/src/org/chromium/base/BundleUtils.java
index 256b01a..f5605fb 100644
--- a/base/android/java/src/org/chromium/base/BundleUtils.java
+++ b/base/android/java/src/org/chromium/base/BundleUtils.java
@@ -130,9 +130,7 @@
return getSplitApkPath(splitName) != null;
}
- /**
- * The lock to hold when calling {@link Context#createContextForSplit(String)}.
- */
+ /** The lock to hold when calling {@link Context#createContextForSplit(String)}. */
public static Object getSplitContextLock() {
return sSplitLock;
}
@@ -173,9 +171,11 @@
// cache, see b/172602571. This should be solved for the chrome ClassLoader by
// SplitCompatAppComponentFactory, but modules which depend on the chrome module need
// special handling here to make sure they have the correct parent.
- boolean shouldReplaceClassLoader = isolatedSplitsEnabled()
- && !parent.equals(BundleUtils.class.getClassLoader()) && appContext != null
- && !parent.equals(appContext.getClassLoader());
+ boolean shouldReplaceClassLoader =
+ isolatedSplitsEnabled()
+ && !parent.equals(BundleUtils.class.getClassLoader())
+ && appContext != null
+ && !parent.equals(appContext.getClassLoader());
synchronized (sCachedClassLoaders) {
if (shouldReplaceClassLoader && !sCachedClassLoaders.containsKey(splitName)) {
String apkPath = getSplitApkPath(splitName);
@@ -230,8 +230,9 @@
// Due to b/171269960 isolated split class loaders have an empty library path, so check
// the base module class loader first which loaded BundleUtils. If the library is not
// found there, attempt to construct the correct library path from the split.
- String path = ((BaseDexClassLoader) BundleUtils.class.getClassLoader())
- .findLibrary(libraryName);
+ String path =
+ ((BaseDexClassLoader) BundleUtils.class.getClassLoader())
+ .findLibrary(libraryName);
if (path != null) {
return path;
}
@@ -257,7 +258,9 @@
ClassLoader activityClassLoader = activity.getClass().getClassLoader();
ClassLoader contextClassLoader = baseContext.getClassLoader();
if (activityClassLoader != contextClassLoader) {
- Log.w(TAG, "Mismatched ClassLoaders between Activity and context (fixing): %s",
+ Log.w(
+ TAG,
+ "Mismatched ClassLoaders between Activity and context (fixing): %s",
activity.getClass());
replaceClassLoader(baseContext, activityClassLoader);
}
@@ -386,9 +389,7 @@
return null;
}
- /**
- * Loads the class with the specified binary name.
- */
+ /** Loads the class with the specified binary name. */
@Override
public Class<?> findClass(String cn) throws ClassNotFoundException {
Class<?> foundClass = checkSplitsClassLoaders(cn);
@@ -409,7 +410,10 @@
return foundClass;
}
}
- Log.w(TAG, "No class %s amongst %s", cn,
+ Log.w(
+ TAG,
+ "No class %s amongst %s",
+ cn,
TextUtils.join("\n", sInflationClassLoaders.keySet()));
}
throw new ClassNotFoundException(cn);
diff --git a/base/android/java/src/org/chromium/base/Callback.java b/base/android/java/src/org/chromium/base/Callback.java
index 00aef7c..4a9fa41 100644
--- a/base/android/java/src/org/chromium/base/Callback.java
+++ b/base/android/java/src/org/chromium/base/Callback.java
@@ -15,9 +15,7 @@
*/
@FunctionalInterface
public interface Callback<T> {
- /**
- * Invoked with the result of a computation.
- */
+ /** Invoked with the result of a computation. */
void onResult(T result);
/**
diff --git a/base/android/java/src/org/chromium/base/CallbackController.java b/base/android/java/src/org/chromium/base/CallbackController.java
index 2dc19a6..8e8e07a 100644
--- a/base/android/java/src/org/chromium/base/CallbackController.java
+++ b/base/android/java/src/org/chromium/base/CallbackController.java
@@ -9,8 +9,7 @@
import java.lang.ref.WeakReference;
import java.util.ArrayList;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.Objects;
import javax.annotation.concurrent.GuardedBy;
@@ -19,9 +18,13 @@
* version of the same, and cancel them in bulk when {@link #destroy()} is called. Use an instance
* of this class to wrap lambdas passed to other objects, and later use {@link #destroy()} to
* prevent future invocations of these lambdas.
- * <p>
- * Example usage:
- * {@code
+ *
+ * <p>Besides helping with lifecycle management, this also prevents holding onto object references
+ * after callbacks have been canceled.
+ *
+ * <p>Example usage:
+ *
+ * <pre>{@code
* public class Foo {
* private CallbackController mCallbackController = new CallbackController();
* private SomeDestructibleClass mDestructible = new SomeDestructibleClass();
@@ -61,20 +64,22 @@
* mDestructible.setBaz(baz);
* }
* }
- * }
- * <p>
- * It does not matter if the lambda is intended to be invoked once or more times, as it is only
+ * }</pre>
+ *
+ * <p>It does not matter if the lambda is intended to be invoked once or more times, as it is only
* weakly referred from this class. When the lambda is no longer needed, it can be safely garbage
* collected. All invocations after {@link #destroy()} will be ignored.
- * <p>
- * Each instance of this class in only meant for a single {@link
- * #destroy()} call. After it is destroyed, the owning class should create a new instance instead:
- * {@code
- * // Somewhere inside Foo.
- * mCallbackController.destroy(); // Invalidates all current callbacks.
- * mCallbackController = new CallbackController(); // Allows to start handing out new callbacks.
- * }
+ *
+ * <p>Each instance of this class in only meant for a single {@link #destroy()} call. After it is
+ * destroyed, the owning class should create a new instance instead:
+ *
+ * <pre>{@code
+ * // Somewhere inside Foo.
+ * mCallbackController.destroy(); // Invalidates all current callbacks.
+ * mCallbackController = new CallbackController(); // Allows to start handing out new callbacks.
+ * }</pre>
*/
+@SuppressWarnings({"NoSynchronizedThisCheck", "NoSynchronizedMethodCheck"})
public final class CallbackController {
/** Interface for cancelable objects tracked by this class. */
private interface Cancelable {
@@ -84,7 +89,7 @@
/** Class wrapping a {@link Callback} interface with a {@link Cancelable} interface. */
private class CancelableCallback<T> implements Cancelable, Callback<T> {
- @GuardedBy("mReentrantLock")
+ @GuardedBy("CallbackController.this")
private Callback<T> mCallback;
private CancelableCallback(@NonNull Callback<T> callback) {
@@ -101,7 +106,7 @@
public void onResult(T result) {
// Guarantees the cancelation is not going to happen, while callback is executed by
// another thread.
- try (AutoCloseableLock acl = AutoCloseableLock.lock(mReentrantLock)) {
+ synchronized (CallbackController.this) {
if (mCallback != null) mCallback.onResult(result);
}
}
@@ -109,7 +114,7 @@
/** Class wrapping {@link Runnable} interface with a {@link Cancelable} interface. */
private class CancelableRunnable implements Cancelable, Runnable {
- @GuardedBy("mReentrantLock")
+ @GuardedBy("CallbackController.this")
private Runnable mRunnable;
private CancelableRunnable(@NonNull Runnable runnable) {
@@ -126,108 +131,79 @@
public void run() {
// Guarantees the cancelation is not going to happen, while runnable is executed by
// another thread.
- try (AutoCloseableLock acl = AutoCloseableLock.lock(mReentrantLock)) {
+ synchronized (CallbackController.this) {
if (mRunnable != null) mRunnable.run();
}
}
}
- /** Class wrapping the locking logic to reduce repetitive code. */
- private static class AutoCloseableLock implements AutoCloseable {
- private final Lock mLock;
- private boolean mIsLocked;
-
- private AutoCloseableLock(Lock lock, boolean isLocked) {
- mLock = lock;
- mIsLocked = isLocked;
- }
-
- static AutoCloseableLock lock(Lock l) {
- l.lock();
- return new AutoCloseableLock(l, true);
- }
-
- @Override
- public void close() {
- if (!mIsLocked) throw new IllegalStateException("mLock isn't locked.");
- mIsLocked = false;
- mLock.unlock();
- }
- }
-
/** A list of cancelables created and cancelable by this object. */
@Nullable
- @GuardedBy("mReentrantLock")
+ @GuardedBy("this")
private ArrayList<WeakReference<Cancelable>> mCancelables = new ArrayList<>();
- /** Ensures thread safety of creating cancelables and canceling them. */
- private final ReentrantLock mReentrantLock = new ReentrantLock(/*fair=*/true);
-
/**
- * Wraps a provided {@link Callback} with a cancelable object that is tracked by this
- * {@link CallbackController}. To cancel a resulting wrapped instance destroy the host.
- * <p>
- * This method must not be called after {@link #destroy()}.
+ * Wraps a provided {@link Callback} with a cancelable object that is tracked by this {@link
+ * CallbackController}. To cancel a resulting wrapped instance destroy the host.
+ *
+ * <p>This method must not be called after {@link #destroy()}.
*
* @param <T> The type of the callback result.
* @param callback A callback that will be made cancelable.
* @return A cancelable instance of the callback.
*/
- public <T> Callback<T> makeCancelable(@NonNull Callback<T> callback) {
- try (AutoCloseableLock acl = AutoCloseableLock.lock(mReentrantLock)) {
- checkNotCanceled();
- CancelableCallback<T> cancelable = new CancelableCallback<>(callback);
- mCancelables.add(new WeakReference<>(cancelable));
- return cancelable;
- }
+ public synchronized <T> Callback<T> makeCancelable(@NonNull Callback<T> callback) {
+ checkNotCanceled();
+ CancelableCallback<T> cancelable = new CancelableCallback<>(callback);
+ addInternal(cancelable);
+ return cancelable;
}
/**
- * Wraps a provided {@link Runnable} with a cancelable object that is tracked by this
- * {@link CallbackController}. To cancel a resulting wrapped instance destroy the host.
- * <p>
- * This method must not be called after {@link #destroy()}.
+ * Wraps a provided {@link Runnable} with a cancelable object that is tracked by this {@link
+ * CallbackController}. To cancel a resulting wrapped instance destroy the host.
+ *
+ * <p>This method must not be called after {@link #destroy()}.
*
* @param runnable A runnable that will be made cancelable.
* @return A cancelable instance of the runnable.
*/
- public Runnable makeCancelable(@NonNull Runnable runnable) {
- try (AutoCloseableLock acl = AutoCloseableLock.lock(mReentrantLock)) {
- checkNotCanceled();
- CancelableRunnable cancelable = new CancelableRunnable(runnable);
- mCancelables.add(new WeakReference<>(cancelable));
- return cancelable;
+ public synchronized Runnable makeCancelable(@NonNull Runnable runnable) {
+ checkNotCanceled();
+ CancelableRunnable cancelable = new CancelableRunnable(runnable);
+ addInternal(cancelable);
+ return cancelable;
+ }
+
+ @GuardedBy("this")
+ private void addInternal(Cancelable cancelable) {
+ var cancelables = mCancelables;
+ cancelables.add(new WeakReference<>(cancelable));
+ // Flush null entries.
+ if ((cancelables.size() % 1024) == 0) {
+ // This removes null entries as a side-effect.
+ // Cloning the list is inefficient, but this should rarely be hit.
+ CollectionUtil.strengthen(cancelables);
}
}
/**
* Cancels all of the cancelables that have not been garbage collected yet.
- * <p>
- * This method must only be called once and makes the instance unusable afterwards.
+ *
+ * <p>This method must only be called once and makes the instance unusable afterwards.
*/
- public void destroy() {
- // This is likely an invalid state. A callback is currently being run, which means the
- // owning class using this controller is likely in the middle of a method call. But if
- // destroy is called on the controller, it is also likely being called on the owning class.
- // After destroy completes, the owning class will be in invalid state to be used, and the
- // rest of the method call will be operating with the owning class in an invalid state. If
- // something has a valid use case for this, remove this assert.
- assert !mReentrantLock.isHeldByCurrentThread();
-
- try (AutoCloseableLock acl = AutoCloseableLock.lock(mReentrantLock)) {
- checkNotCanceled();
- for (Cancelable cancelable : CollectionUtil.strengthen(mCancelables)) {
- cancelable.cancel();
- }
- mCancelables = null;
+ public synchronized void destroy() {
+ checkNotCanceled();
+ for (Cancelable cancelable : CollectionUtil.strengthen(mCancelables)) {
+ cancelable.cancel();
}
+ mCancelables = null;
}
/** If the cancelation already happened, throws an {@link IllegalStateException}. */
- @GuardedBy("mReentrantLock")
+ @GuardedBy("this")
private void checkNotCanceled() {
- if (mCancelables == null) {
- throw new IllegalStateException("This CallbackController has already been destroyed.");
- }
+ // Use NullPointerException because it optimizes well.
+ Objects.requireNonNull(mCancelables);
}
}
diff --git a/base/android/java/src/org/chromium/base/CommandLine.java b/base/android/java/src/org/chromium/base/CommandLine.java
index 72091a0..e6d758b 100644
--- a/base/android/java/src/org/chromium/base/CommandLine.java
+++ b/base/android/java/src/org/chromium/base/CommandLine.java
@@ -21,11 +21,10 @@
import java.util.concurrent.atomic.AtomicReference;
/**
- * Java mirror of base/command_line.h.
- * Android applications don't have command line arguments. Instead, they're "simulated" by reading a
- * file at a specific location early during startup. Applications each define their own files, e.g.,
- * ContentShellApplication.COMMAND_LINE_FILE.
-**/
+ * Java mirror of base/command_line.h. Android applications don't have command line arguments.
+ * Instead, they're "simulated" by reading a file at a specific location early during startup.
+ * Applications each define their own files, e.g., ContentShellApplication.COMMAND_LINE_FILE.
+ */
public abstract class CommandLine {
// Public abstract interface, implemented in derived classes.
// All these methods reflect their native-side counterparts.
@@ -54,9 +53,7 @@
return TextUtils.isEmpty(value) ? defaultValue : value;
}
- /**
- * Return a copy of all switches, along with their values.
- */
+ /** Return a copy of all switches, along with their values. */
public abstract Map getSwitches();
/**
@@ -441,12 +438,19 @@
@NativeMethods
interface Natives {
void init(String[] args);
+
boolean hasSwitch(String switchString);
+
String getSwitchValue(String switchString);
+
String[] getSwitchesFlattened();
+
void appendSwitch(String switchString);
+
void appendSwitchWithValue(String switchString, String value);
+
void appendSwitchesAndArguments(String[] array);
+
void removeSwitch(String switchString);
}
}
diff --git a/base/android/java/src/org/chromium/base/CommandLineInitUtil.java b/base/android/java/src/org/chromium/base/CommandLineInitUtil.java
index b0cdcc3..12be43e 100644
--- a/base/android/java/src/org/chromium/base/CommandLineInitUtil.java
+++ b/base/android/java/src/org/chromium/base/CommandLineInitUtil.java
@@ -13,9 +13,7 @@
import java.io.File;
-/**
- * Provides implementation of command line initialization for Android.
- */
+/** Provides implementation of command line initialization for Android. */
public final class CommandLineInitUtil {
/**
* The location of the command line file needs to be in a protected
@@ -34,17 +32,12 @@
*/
private static final String COMMAND_LINE_FILE_PATH_DEBUG_APP = "/data/local/tmp";
- /**
- * The name of the command line file to pull arguments from.
- */
+ /** The name of the command line file to pull arguments from. */
private static String sFilenameOverrideForTesting;
- private CommandLineInitUtil() {
- }
+ private CommandLineInitUtil() {}
- /**
- * Set the filename to use.
- */
+ /** Set the filename to use. */
public static void setFilenameOverrideForTesting(String value) {
sFilenameOverrideForTesting = value;
}
@@ -93,11 +86,12 @@
}
private static String getDebugApp(Context context) {
- boolean adbEnabled = Settings.Global.getInt(context.getContentResolver(),
- Settings.Global.ADB_ENABLED, 0) == 1;
+ boolean adbEnabled =
+ Settings.Global.getInt(context.getContentResolver(), Settings.Global.ADB_ENABLED, 0)
+ == 1;
if (adbEnabled) {
- return Settings.Global.getString(context.getContentResolver(),
- Settings.Global.DEBUG_APP);
+ return Settings.Global.getString(
+ context.getContentResolver(), Settings.Global.DEBUG_APP);
}
return null;
}
diff --git a/base/android/java/src/org/chromium/base/ContentUriUtils.java b/base/android/java/src/org/chromium/base/ContentUriUtils.java
index a1eb000..2381044 100644
--- a/base/android/java/src/org/chromium/base/ContentUriUtils.java
+++ b/base/android/java/src/org/chromium/base/ContentUriUtils.java
@@ -23,9 +23,7 @@
import java.io.File;
import java.io.IOException;
-/**
- * This class provides methods to access content URI schemes.
- */
+/** This class provides methods to access content URI schemes. */
public abstract class ContentUriUtils {
private static final String TAG = "ContentUriUtils";
private static FileProviderUtil sFileProviderUtil;
@@ -227,8 +225,11 @@
Uri uri = Uri.parse(uriString);
try {
- String displayName = getDisplayName(uri, ContextUtils.getApplicationContext(),
- MediaStore.MediaColumns.DISPLAY_NAME);
+ String displayName =
+ getDisplayName(
+ uri,
+ ContextUtils.getApplicationContext(),
+ MediaStore.MediaColumns.DISPLAY_NAME);
return TextUtils.isEmpty(displayName) ? null : displayName;
} catch (Exception e) {
// There are a few Exceptions we can hit here (e.g. SecurityException), but we don't
diff --git a/base/android/java/src/org/chromium/base/ContextUtils.java b/base/android/java/src/org/chromium/base/ContextUtils.java
index fbb8718..74376af 100644
--- a/base/android/java/src/org/chromium/base/ContextUtils.java
+++ b/base/android/java/src/org/chromium/base/ContextUtils.java
@@ -26,9 +26,7 @@
import org.chromium.base.compat.ApiHelperForO;
import org.chromium.build.BuildConfig;
-/**
- * This class provides Android application context related utility methods.
- */
+/** This class provides Android application context related utility methods. */
@JNINamespace("base::android")
public class ContextUtils {
private static final String TAG = "ContextUtils";
@@ -41,11 +39,10 @@
* TODO(mthiesse): Move to ApiHelperForT when we build against T SDK.
*/
public static final int RECEIVER_EXPORTED = 0x2;
+
public static final int RECEIVER_NOT_EXPORTED = 0x4;
- /**
- * Initialization-on-demand holder. This exists for thread-safe lazy initialization.
- */
+ /** Initialization-on-demand holder. This exists for thread-safe lazy initialization. */
private static class Holder {
// Not final for tests.
private static SharedPreferences sSharedPreferences = fetchAppSharedPreferences();
@@ -78,7 +75,8 @@
public static void initApplicationContext(Context appContext) {
// Conceding that occasionally in tests, native is loaded before the browser process is
// started, in which case the browser process re-sets the application context.
- assert sApplicationContext == null || sApplicationContext == appContext
+ assert sApplicationContext == null
+ || sApplicationContext == appContext
|| ((ContextWrapper) sApplicationContext).getBaseContext() == appContext;
initJavaSideApplicationContext(appContext);
}
@@ -225,13 +223,13 @@
public static Intent registerProtectedBroadcastReceiver(
Context context, BroadcastReceiver receiver, IntentFilter filter) {
return registerBroadcastReceiver(
- context, receiver, filter, /*permission=*/null, /*scheduler=*/null, 0);
+ context, receiver, filter, /* permission= */ null, /* scheduler= */ null, 0);
}
public static Intent registerProtectedBroadcastReceiver(
Context context, BroadcastReceiver receiver, IntentFilter filter, Handler scheduler) {
return registerBroadcastReceiver(
- context, receiver, filter, /*permission=*/null, scheduler, 0);
+ context, receiver, filter, /* permission= */ null, scheduler, 0);
}
/**
@@ -249,7 +247,7 @@
public static Intent registerExportedBroadcastReceiver(
Context context, BroadcastReceiver receiver, IntentFilter filter, String permission) {
return registerBroadcastReceiver(
- context, receiver, filter, permission, /*scheduler=*/null, RECEIVER_EXPORTED);
+ context, receiver, filter, permission, /* scheduler= */ null, RECEIVER_EXPORTED);
}
/**
@@ -286,18 +284,33 @@
*/
public static Intent registerNonExportedBroadcastReceiver(
Context context, BroadcastReceiver receiver, IntentFilter filter) {
- return registerBroadcastReceiver(context, receiver, filter, /*permission=*/null,
- /*scheduler=*/null, RECEIVER_NOT_EXPORTED);
+ return registerBroadcastReceiver(
+ context,
+ receiver,
+ filter,
+ /* permission= */ null,
+ /* scheduler= */ null,
+ RECEIVER_NOT_EXPORTED);
}
public static Intent registerNonExportedBroadcastReceiver(
Context context, BroadcastReceiver receiver, IntentFilter filter, Handler scheduler) {
return registerBroadcastReceiver(
- context, receiver, filter, /*permission=*/null, scheduler, RECEIVER_NOT_EXPORTED);
+ context,
+ receiver,
+ filter,
+ /* permission= */ null,
+ scheduler,
+ RECEIVER_NOT_EXPORTED);
}
- private static Intent registerBroadcastReceiver(Context context, BroadcastReceiver receiver,
- IntentFilter filter, String permission, Handler scheduler, int flags) {
+ private static Intent registerBroadcastReceiver(
+ Context context,
+ BroadcastReceiver receiver,
+ IntentFilter filter,
+ String permission,
+ Handler scheduler,
+ int flags) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return ApiHelperForO.registerReceiver(
context, receiver, filter, permission, scheduler, flags);
diff --git a/base/android/java/src/org/chromium/base/CpuFeatures.java b/base/android/java/src/org/chromium/base/CpuFeatures.java
index a98460a..b2d9fe1 100644
--- a/base/android/java/src/org/chromium/base/CpuFeatures.java
+++ b/base/android/java/src/org/chromium/base/CpuFeatures.java
@@ -22,9 +22,7 @@
//
@JNINamespace("base::android")
public abstract class CpuFeatures {
- /**
- * Return the number of CPU Cores on the device.
- */
+ /** Return the number of CPU Cores on the device. */
public static int getCount() {
return CpuFeaturesJni.get().getCoreCount();
}
@@ -41,6 +39,7 @@
@NativeMethods
interface Natives {
int getCoreCount();
+
long getCpuFeatures();
}
}
diff --git a/base/android/java/src/org/chromium/base/DiscardableReferencePool.java b/base/android/java/src/org/chromium/base/DiscardableReferencePool.java
index 34723ef..6a84e43 100644
--- a/base/android/java/src/org/chromium/base/DiscardableReferencePool.java
+++ b/base/android/java/src/org/chromium/base/DiscardableReferencePool.java
@@ -40,8 +40,7 @@
* @param <T> The type of the object.
*/
public static class DiscardableReference<T> {
- @Nullable
- private T mPayload;
+ @Nullable private T mPayload;
private DiscardableReference(T payload) {
assert payload != null;
@@ -56,9 +55,7 @@
return mPayload;
}
- /**
- * Clear the referent.
- */
+ /** Clear the referent. */
private void discard() {
assert mPayload != null;
mPayload = null;
diff --git a/base/android/java/src/org/chromium/base/EarlyTraceEvent.java b/base/android/java/src/org/chromium/base/EarlyTraceEvent.java
index d6df3af..f40dfba 100644
--- a/base/android/java/src/org/chromium/base/EarlyTraceEvent.java
+++ b/base/android/java/src/org/chromium/base/EarlyTraceEvent.java
@@ -78,10 +78,8 @@
// - disable(): ENABLED -> FINISHED
@VisibleForTesting static final int STATE_DISABLED = 0;
@VisibleForTesting static final int STATE_ENABLED = 1;
- @VisibleForTesting
- static final int STATE_FINISHED = 2;
- @VisibleForTesting
- static volatile int sState = STATE_DISABLED;
+ @VisibleForTesting static final int STATE_FINISHED = 2;
+ @VisibleForTesting static volatile int sState = STATE_DISABLED;
// In child processes the CommandLine is not available immediately, so early tracing is enabled
// unconditionally in Chrome. This flag allows not to enable early tracing twice in this case.
@@ -108,13 +106,13 @@
public static final String TRACE_EARLY_JAVA_IN_CHILD_SWITCH = "trace-early-java-in-child";
// Protects the fields below.
- @VisibleForTesting
- static final Object sLock = new Object();
+ @VisibleForTesting static final Object sLock = new Object();
// Not final because in many configurations these objects are not used.
@GuardedBy("sLock")
@VisibleForTesting
static List<Event> sEvents;
+
@GuardedBy("sLock")
@VisibleForTesting
static List<AsyncEvent> sAsyncEvents;
@@ -123,7 +121,7 @@
static void maybeEnableInBrowserProcess() {
ThreadUtils.assertOnUiThread();
assert !sEnabledInChildProcessBeforeCommandLine
- : "Should not have been initialized in a child process";
+ : "Should not have been initialized in a child process";
if (sState != STATE_DISABLED) return;
boolean shouldEnable = false;
// Checking for the trace config filename touches the disk.
@@ -138,8 +136,8 @@
// Access denied, not enabled.
}
}
- if (ContextUtils.getAppSharedPreferences().getBoolean(
- BACKGROUND_STARTUP_TRACING_ENABLED_KEY, false)) {
+ if (ContextUtils.getAppSharedPreferences()
+ .getBoolean(BACKGROUND_STARTUP_TRACING_ENABLED_KEY, false)) {
if (shouldEnable) {
// If user has enabled tracing, then force disable background tracing for this
// session.
@@ -156,9 +154,7 @@
if (shouldEnable) enable();
}
- /**
- * Enables early tracing in child processes before CommandLine arrives there.
- */
+ /** Enables early tracing in child processes before CommandLine arrives there. */
public static void earlyEnableInChildWithoutCommandLine() {
sEnabledInChildProcessBeforeCommandLine = true;
assert sState == STATE_DISABLED;
@@ -219,9 +215,7 @@
}
}
- /**
- * Stops early tracing without flushing the buffered events.
- */
+ /** Stops early tracing without flushing the buffered events. */
@VisibleForTesting
static void reset() {
synchronized (sLock) {
@@ -235,9 +229,7 @@
return sState == STATE_ENABLED;
}
- /**
- * Sets the background startup tracing enabled in app preferences for next startup.
- */
+ /** Sets the background startup tracing enabled in app preferences for next startup. */
@CalledByNative
static void setBackgroundStartupTracingFlag(boolean enabled) {
// Setting preferences might cause a disk write
@@ -265,7 +257,7 @@
// begin() and end() are going to be called once per TraceEvent, this avoids entering a
// synchronized block at each and every call.
if (!enabled()) return;
- Event event = new Event(name, true /*isStart*/, isToplevel);
+ Event event = new Event(name, /* isStart= */ true, isToplevel);
synchronized (sLock) {
if (!enabled()) return;
sEvents.add(event);
@@ -275,7 +267,7 @@
/** @see TraceEvent#end */
public static void end(String name, boolean isToplevel) {
if (!enabled()) return;
- Event event = new Event(name, false /*isStart*/, isToplevel);
+ Event event = new Event(name, /* isStart= */ false, isToplevel);
synchronized (sLock) {
if (!enabled()) return;
sEvents.add(event);
@@ -285,7 +277,7 @@
/** @see TraceEvent#startAsync */
public static void startAsync(String name, long id) {
if (!enabled()) return;
- AsyncEvent event = new AsyncEvent(name, id, true /*isStart*/);
+ AsyncEvent event = new AsyncEvent(name, id, /* isStart= */ true);
synchronized (sLock) {
if (!enabled()) return;
sAsyncEvents.add(event);
@@ -295,7 +287,7 @@
/** @see TraceEvent#finishAsync */
public static void finishAsync(String name, long id) {
if (!enabled()) return;
- AsyncEvent event = new AsyncEvent(name, id, false /*isStart*/);
+ AsyncEvent event = new AsyncEvent(name, id, /* isStart= */ false);
synchronized (sLock) {
if (!enabled()) return;
sAsyncEvents.add(event);
@@ -318,19 +310,23 @@
for (Event e : events) {
if (e.mIsStart) {
if (e.mIsToplevel) {
- EarlyTraceEventJni.get().recordEarlyToplevelBeginEvent(
- e.mName, e.mTimeNanos, e.mThreadId, e.mThreadTimeMillis);
+ EarlyTraceEventJni.get()
+ .recordEarlyToplevelBeginEvent(
+ e.mName, e.mTimeNanos, e.mThreadId, e.mThreadTimeMillis);
} else {
- EarlyTraceEventJni.get().recordEarlyBeginEvent(
- e.mName, e.mTimeNanos, e.mThreadId, e.mThreadTimeMillis);
+ EarlyTraceEventJni.get()
+ .recordEarlyBeginEvent(
+ e.mName, e.mTimeNanos, e.mThreadId, e.mThreadTimeMillis);
}
} else {
if (e.mIsToplevel) {
- EarlyTraceEventJni.get().recordEarlyToplevelEndEvent(
- e.mName, e.mTimeNanos, e.mThreadId, e.mThreadTimeMillis);
+ EarlyTraceEventJni.get()
+ .recordEarlyToplevelEndEvent(
+ e.mName, e.mTimeNanos, e.mThreadId, e.mThreadTimeMillis);
} else {
- EarlyTraceEventJni.get().recordEarlyEndEvent(
- e.mName, e.mTimeNanos, e.mThreadId, e.mThreadTimeMillis);
+ EarlyTraceEventJni.get()
+ .recordEarlyEndEvent(
+ e.mName, e.mTimeNanos, e.mThreadId, e.mThreadTimeMillis);
}
}
}
@@ -349,12 +345,17 @@
@NativeMethods
interface Natives {
void recordEarlyBeginEvent(String name, long timeNanos, int threadId, long threadMillis);
+
void recordEarlyEndEvent(String name, long timeNanos, int threadId, long threadMillis);
+
void recordEarlyToplevelBeginEvent(
String name, long timeNanos, int threadId, long threadMillis);
+
void recordEarlyToplevelEndEvent(
String name, long timeNanos, int threadId, long threadMillis);
+
void recordEarlyAsyncBeginEvent(String name, long id, long timeNanos);
+
void recordEarlyAsyncEndEvent(long id, long timeNanos);
}
}
diff --git a/base/android/java/src/org/chromium/base/EventLog.java b/base/android/java/src/org/chromium/base/EventLog.java
index 1804add..6f09010 100644
--- a/base/android/java/src/org/chromium/base/EventLog.java
+++ b/base/android/java/src/org/chromium/base/EventLog.java
@@ -7,9 +7,7 @@
import org.jni_zero.CalledByNative;
import org.jni_zero.JNINamespace;
-/**
- * A simple interface to Android's EventLog to be used by native code.
- */
+/** A simple interface to Android's EventLog to be used by native code. */
@JNINamespace("base::android")
public class EventLog {
diff --git a/base/android/java/src/org/chromium/base/FeatureList.java b/base/android/java/src/org/chromium/base/FeatureList.java
index 319074b..96df7ab 100644
--- a/base/android/java/src/org/chromium/base/FeatureList.java
+++ b/base/android/java/src/org/chromium/base/FeatureList.java
@@ -18,40 +18,28 @@
import java.util.HashMap;
import java.util.Map;
-/**
- * Provides shared capabilities for feature flag support.
- */
+/** Provides shared capabilities for feature flag support. */
@JNINamespace("base::android")
public class FeatureList {
- /**
- * Test value overrides for tests without native.
- */
+ /** Test value overrides for tests without native. */
public static class TestValues {
private Map<String, Boolean> mFeatureFlags = new HashMap<>();
private Map<String, Map<String, String>> mFieldTrialParams = new HashMap<>();
- /**
- * Constructor.
- */
+ /** Constructor. */
public TestValues() {}
- /**
- * Set overrides for feature flags.
- */
+ /** Set overrides for feature flags. */
public void setFeatureFlagsOverride(Map<String, Boolean> featureFlags) {
mFeatureFlags = featureFlags;
}
- /**
- * Add an override for a feature flag.
- */
+ /** Add an override for a feature flag. */
public void addFeatureFlagOverride(String featureName, boolean testValue) {
mFeatureFlags.put(featureName, testValue);
}
- /**
- * Add an override for a field trial parameter.
- */
+ /** Add an override for a field trial parameter. */
public void addFieldTrialParamOverride(
String featureName, String paramName, String testValue) {
Map<String, String> featureParams = mFieldTrialParams.get(featureName);
@@ -128,9 +116,7 @@
sTestCanUseDefaults = false;
}
- /**
- * Sets the feature flags to use in JUnit tests, since native calls are not available there.
- */
+ /** Sets the feature flags to use in JUnit tests, since native calls are not available there. */
@VisibleForTesting
public static void setTestFeatures(Map<String, Boolean> testFeatures) {
if (testFeatures == null) {
@@ -207,7 +193,11 @@
* @return Whether the feature has a test value configured.
*/
public static boolean hasTestFeature(String featureName) {
- return hasTestFeatures() && sTestFeatures.mFeatureFlags.containsKey(featureName);
+ // TODO(crbug.com/1434471)): Copy into a local reference to avoid race conditions
+ // like crbug.com/1494095 unsetting the test features. Locking down flag state will allow
+ // this mitigation to be removed.
+ TestValues testValues = sTestFeatures;
+ return testValues != null && testValues.mFeatureFlags.containsKey(featureName);
}
/**
@@ -218,16 +208,22 @@
* @throws IllegalArgumentException if no test value was set and default values aren't allowed.
*/
public static Boolean getTestValueForFeature(String featureName) {
- if (hasTestFeatures()) {
- Boolean override = sTestFeatures.getFeatureFlagOverride(featureName);
+ // TODO(crbug.com/1434471)): Copy into a local reference to avoid race conditions
+ // like crbug.com/1494095 unsetting the test features. Locking down flag state will allow
+ // this mitigation to be removed.
+ TestValues testValues = sTestFeatures;
+ if (testValues != null) {
+ Boolean override = testValues.getFeatureFlagOverride(featureName);
if (override != null) {
return override;
}
if (!sTestCanUseDefaults) {
- throw new IllegalArgumentException("No test value configured for " + featureName
- + " and native is not available to provide a default value. Use"
- + " @EnableFeatures or @DisableFeatures to provide test values for the"
- + " flag.");
+ throw new IllegalArgumentException(
+ "No test value configured for "
+ + featureName
+ + " and native is not available to provide a default value. Use"
+ + " @EnableFeatures or @DisableFeatures to provide test values for"
+ + " the flag.");
}
}
return null;
@@ -241,8 +237,12 @@
* @return The test value set for the parameter, or null if no test value has been set.
*/
public static String getTestValueForFieldTrialParam(String featureName, String paramName) {
- if (hasTestFeatures()) {
- return sTestFeatures.getFieldTrialParamOverride(featureName, paramName);
+ // TODO(crbug.com/1434471)): Copy into a local reference to avoid race conditions
+ // like crbug.com/1494095 unsetting the test features. Locking down flag state will allow
+ // this mitigation to be removed.
+ TestValues testValues = sTestFeatures;
+ if (testValues != null) {
+ return testValues.getFieldTrialParamOverride(featureName, paramName);
}
return null;
}
@@ -256,8 +256,12 @@
*/
public static Map<String, String> getTestValuesForAllFieldTrialParamsForFeature(
String featureName) {
- if (hasTestFeatures()) {
- return sTestFeatures.getAllFieldTrialParamOverridesForFeature(featureName);
+ // TODO(crbug.com/1434471)): Copy into a local reference to avoid race conditions
+ // like crbug.com/1494095 unsetting the test features. Locking down flag state will allow
+ // this mitigation to be removed.
+ TestValues testValues = sTestFeatures;
+ if (testValues != null) {
+ return testValues.getAllFieldTrialParamOverridesForFeature(featureName);
}
return null;
}
diff --git a/base/android/java/src/org/chromium/base/FeatureMap.java b/base/android/java/src/org/chromium/base/FeatureMap.java
index 379e123..cf851dc 100644
--- a/base/android/java/src/org/chromium/base/FeatureMap.java
+++ b/base/android/java/src/org/chromium/base/FeatureMap.java
@@ -25,6 +25,7 @@
@JNINamespace("base::android")
public abstract class FeatureMap {
private long mNativeMapPtr;
+
protected FeatureMap() {}
/**
@@ -65,8 +66,8 @@
if (testValue != null) return testValue;
if (FeatureList.hasTestFeatures()) return "";
ensureNativeMapInit();
- return FeatureMapJni.get().getFieldTrialParamByFeature(
- mNativeMapPtr, featureName, paramName);
+ return FeatureMapJni.get()
+ .getFieldTrialParamByFeature(mNativeMapPtr, featureName, paramName);
}
/**
@@ -84,8 +85,9 @@
if (testValue != null) return Boolean.valueOf(testValue);
if (FeatureList.hasTestFeatures()) return defaultValue;
ensureNativeMapInit();
- return FeatureMapJni.get().getFieldTrialParamByFeatureAsBoolean(
- mNativeMapPtr, featureName, paramName, defaultValue);
+ return FeatureMapJni.get()
+ .getFieldTrialParamByFeatureAsBoolean(
+ mNativeMapPtr, featureName, paramName, defaultValue);
}
/**
@@ -103,8 +105,9 @@
if (testValue != null) return Integer.valueOf(testValue);
if (FeatureList.hasTestFeatures()) return defaultValue;
ensureNativeMapInit();
- return FeatureMapJni.get().getFieldTrialParamByFeatureAsInt(
- mNativeMapPtr, featureName, paramName, defaultValue);
+ return FeatureMapJni.get()
+ .getFieldTrialParamByFeatureAsInt(
+ mNativeMapPtr, featureName, paramName, defaultValue);
}
/**
@@ -122,13 +125,12 @@
if (testValue != null) return Double.valueOf(testValue);
if (FeatureList.hasTestFeatures()) return defaultValue;
ensureNativeMapInit();
- return FeatureMapJni.get().getFieldTrialParamByFeatureAsDouble(
- mNativeMapPtr, featureName, paramName, defaultValue);
+ return FeatureMapJni.get()
+ .getFieldTrialParamByFeatureAsDouble(
+ mNativeMapPtr, featureName, paramName, defaultValue);
}
- /**
- * Returns all the field trial parameters for the specified feature.
- */
+ /** Returns all the field trial parameters for the specified feature. */
public Map<String, String> getFieldTrialParamsForFeature(String featureName) {
Map<String, String> testValues =
FeatureList.getTestValuesForAllFieldTrialParamsForFeature(featureName);
@@ -137,14 +139,21 @@
ensureNativeMapInit();
Map<String, String> result = new HashMap<>();
- String[] flattenedParams = FeatureMapJni.get().getFlattedFieldTrialParamsForFeature(
- mNativeMapPtr, featureName);
+ String[] flattenedParams =
+ FeatureMapJni.get()
+ .getFlattedFieldTrialParamsForFeature(mNativeMapPtr, featureName);
for (int i = 0; i < flattenedParams.length; i += 2) {
result.put(flattenedParams[i], flattenedParams[i + 1]);
}
return result;
}
+ /** Create a {@link MutableFlagWithSafeDefault} in this FeatureMap. */
+ public MutableFlagWithSafeDefault mutableFlagWithSafeDefault(
+ String featureName, boolean defaultValue) {
+ return new MutableFlagWithSafeDefault(this, featureName, defaultValue);
+ }
+
private void ensureNativeMapInit() {
assert FeatureList.isNativeInitialized();
@@ -157,13 +166,18 @@
@NativeMethods
interface Natives {
boolean isEnabled(long featureMap, String featureName);
+
String getFieldTrialParamByFeature(long featureMap, String featureName, String paramName);
+
int getFieldTrialParamByFeatureAsInt(
long featureMap, String featureName, String paramName, int defaultValue);
+
double getFieldTrialParamByFeatureAsDouble(
long featureMap, String featureName, String paramName, double defaultValue);
+
boolean getFieldTrialParamByFeatureAsBoolean(
long featureMap, String featureName, String paramName, boolean defaultValue);
+
String[] getFlattedFieldTrialParamsForFeature(long featureMap, String featureName);
}
}
diff --git a/base/android/java/src/org/chromium/base/Features.java b/base/android/java/src/org/chromium/base/Features.java
index 88178dd..e5c0414 100644
--- a/base/android/java/src/org/chromium/base/Features.java
+++ b/base/android/java/src/org/chromium/base/Features.java
@@ -43,8 +43,8 @@
* specified parameter does not exist or its string value is neither "true" nor "false".
*/
public boolean getFieldTrialParamByFeatureAsBoolean(String paramName, boolean defaultValue) {
- return FeaturesJni.get().getFieldTrialParamByFeatureAsBoolean(
- getFeaturePointer(), paramName, defaultValue);
+ return FeaturesJni.get()
+ .getFieldTrialParamByFeatureAsBoolean(getFeaturePointer(), paramName, defaultValue);
}
/**
@@ -56,8 +56,8 @@
* specified parameter does not exist.
*/
public String getFieldTrialParamByFeatureAsString(String paramName) {
- return FeaturesJni.get().getFieldTrialParamByFeatureAsString(
- getFeaturePointer(), paramName);
+ return FeaturesJni.get()
+ .getFieldTrialParamByFeatureAsString(getFeaturePointer(), paramName);
}
/** Returns a pointer to the native Feature object represented by this object instance. */
@@ -66,8 +66,10 @@
@NativeMethods
interface Natives {
boolean isEnabled(long featurePointer);
+
boolean getFieldTrialParamByFeatureAsBoolean(
long featurePointer, String paramName, boolean defaultValue);
+
String getFieldTrialParamByFeatureAsString(long featurePointer, String paramName);
}
}
diff --git a/base/android/java/src/org/chromium/base/FieldTrialList.java b/base/android/java/src/org/chromium/base/FieldTrialList.java
index 7cb5f4c..137c85c 100644
--- a/base/android/java/src/org/chromium/base/FieldTrialList.java
+++ b/base/android/java/src/org/chromium/base/FieldTrialList.java
@@ -6,9 +6,7 @@
import org.jni_zero.NativeMethods;
-/**
- * Helper to get field trial information.
- */
+/** Helper to get field trial information. */
public class FieldTrialList {
private FieldTrialList() {}
@@ -60,9 +58,13 @@
@NativeMethods
interface Natives {
String findFullName(String trialName);
+
boolean trialExists(String trialName);
+
String getVariationParameter(String trialName, String parameterKey);
+
void logActiveTrials();
+
boolean createFieldTrial(String trialName, String groupName);
}
}
diff --git a/base/android/java/src/org/chromium/base/FileUtils.java b/base/android/java/src/org/chromium/base/FileUtils.java
index 627f494..a07274f 100644
--- a/base/android/java/src/org/chromium/base/FileUtils.java
+++ b/base/android/java/src/org/chromium/base/FileUtils.java
@@ -27,9 +27,7 @@
import java.util.Locale;
import java.util.function.Function;
-/**
- * Helper methods for dealing with Files.
- */
+/** Helper methods for dealing with Files. */
@JNINamespace("base::android")
public class FileUtils {
private static final String TAG = "FileUtils";
@@ -114,9 +112,7 @@
}
}
- /**
- * Performs a simple copy of inputStream to outputStream.
- */
+ /** Performs a simple copy of inputStream to outputStream. */
public static void copyStream(InputStream inputStream, OutputStream outputStream)
throws IOException {
byte[] buffer = new byte[8192];
@@ -143,9 +139,7 @@
}
}
- /**
- * Reads inputStream into a byte array.
- */
+ /** Reads inputStream into a byte array. */
@NonNull
public static byte[] readStream(InputStream inputStream) throws IOException {
ByteArrayOutputStream data = new ByteArrayOutputStream();
@@ -192,7 +186,7 @@
@Nullable
public static Bitmap queryBitmapFromContentProvider(Context context, Uri uri) {
try (ParcelFileDescriptor parcelFileDescriptor =
- context.getContentResolver().openFileDescriptor(uri, "r")) {
+ context.getContentResolver().openFileDescriptor(uri, "r")) {
if (parcelFileDescriptor == null) {
Log.w(TAG, "Null ParcelFileDescriptor from uri " + uri);
return null;
@@ -226,9 +220,7 @@
@NativeMethods
public interface Natives {
- /**
- * Returns the canonicalised absolute pathname for |filePath|.
- */
+ /** Returns the canonicalised absolute pathname for |filePath|. */
String getAbsoluteFilePath(String filePath);
}
}
diff --git a/base/android/java/src/org/chromium/base/Flag.java b/base/android/java/src/org/chromium/base/Flag.java
index a496bf8..1570195 100644
--- a/base/android/java/src/org/chromium/base/Flag.java
+++ b/base/android/java/src/org/chromium/base/Flag.java
@@ -27,8 +27,7 @@
protected Flag(String featureName) {
assert !sFlagsCreated.containsKey(featureName)
- : "Duplicate flag creation for feature: "
- + featureName;
+ : "Duplicate flag creation for feature: " + featureName;
mFeatureName = featureName;
sFlagsCreated.put(mFeatureName, this);
}
diff --git a/base/android/java/src/org/chromium/base/IntentUtils.java b/base/android/java/src/org/chromium/base/IntentUtils.java
index 24a3c2d..45a4f54 100644
--- a/base/android/java/src/org/chromium/base/IntentUtils.java
+++ b/base/android/java/src/org/chromium/base/IntentUtils.java
@@ -27,33 +27,24 @@
import java.io.Serializable;
import java.util.ArrayList;
-/**
- * Utilities dealing with extracting information from intents and creating common intents.
- */
+/** Utilities dealing with extracting information from intents and creating common intents. */
public class IntentUtils {
private static final String TAG = "IntentUtils";
- /**
- * The scheme for referrer coming from an application.
- */
+ /** The scheme for referrer coming from an application. */
public static final String ANDROID_APP_REFERRER_SCHEME = "android-app";
- /**
- * Intent extra used to identify the sending application.
- */
+ /** Intent extra used to identify the sending application. */
public static final String TRUSTED_APPLICATION_CODE_EXTRA = "trusted_application_code_extra";
- /**
- * Fake ComponentName used in constructing TRUSTED_APPLICATION_CODE_EXTRA.
- */
+ /** Fake ComponentName used in constructing TRUSTED_APPLICATION_CODE_EXTRA. */
private static ComponentName sFakeComponentName;
+
private static final Object COMPONENT_NAME_LOCK = new Object();
private static boolean sForceTrustedIntentForTesting;
- /**
- * Just like {@link Intent#hasExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#hasExtra(String)} but doesn't throw exceptions. */
public static boolean safeHasExtra(Intent intent, String name) {
try {
return intent.hasExtra(name);
@@ -64,9 +55,7 @@
}
}
- /**
- * Just like {@link Intent#removeExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#removeExtra(String)} but doesn't throw exceptions. */
public static void safeRemoveExtra(Intent intent, String name) {
try {
intent.removeExtra(name);
@@ -76,9 +65,7 @@
}
}
- /**
- * Just like {@link Intent#getBooleanExtra(String, boolean)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getBooleanExtra(String, boolean)} but doesn't throw exceptions. */
public static boolean safeGetBooleanExtra(Intent intent, String name, boolean defaultValue) {
try {
return intent.getBooleanExtra(name, defaultValue);
@@ -89,9 +76,7 @@
}
}
- /**
- * Just like {@link Bundle#getBoolean(String, boolean)} but doesn't throw exceptions.
- */
+ /** Just like {@link Bundle#getBoolean(String, boolean)} but doesn't throw exceptions. */
public static boolean safeGetBoolean(Bundle bundle, String name, boolean defaultValue) {
try {
return bundle.getBoolean(name, defaultValue);
@@ -102,9 +87,7 @@
}
}
- /**
- * Just like {@link Intent#getIntExtra(String, int)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getIntExtra(String, int)} but doesn't throw exceptions. */
public static int safeGetIntExtra(Intent intent, String name, int defaultValue) {
try {
return intent.getIntExtra(name, defaultValue);
@@ -115,9 +98,7 @@
}
}
- /**
- * Just like {@link Bundle#getInt(String, int)} but doesn't throw exceptions.
- */
+ /** Just like {@link Bundle#getInt(String, int)} but doesn't throw exceptions. */
public static int safeGetInt(Bundle bundle, String name, int defaultValue) {
try {
return bundle.getInt(name, defaultValue);
@@ -128,9 +109,7 @@
}
}
- /**
- * Just like {@link Intent#getIntArrayExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getIntArrayExtra(String)} but doesn't throw exceptions. */
public static int[] safeGetIntArrayExtra(Intent intent, String name) {
try {
return intent.getIntArrayExtra(name);
@@ -141,9 +120,7 @@
}
}
- /**
- * Just like {@link Bundle#getIntArray(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Bundle#getIntArray(String)} but doesn't throw exceptions. */
public static int[] safeGetIntArray(Bundle bundle, String name) {
try {
return bundle.getIntArray(name);
@@ -154,9 +131,7 @@
}
}
- /**
- * Just like {@link Bundle#getFloatArray(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Bundle#getFloatArray(String)} but doesn't throw exceptions. */
public static float[] safeGetFloatArray(Bundle bundle, String name) {
try {
return bundle.getFloatArray(name);
@@ -167,9 +142,7 @@
}
}
- /**
- * Just like {@link Intent#getLongExtra(String, long)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getLongExtra(String, long)} but doesn't throw exceptions. */
public static long safeGetLongExtra(Intent intent, String name, long defaultValue) {
try {
return intent.getLongExtra(name, defaultValue);
@@ -180,9 +153,7 @@
}
}
- /**
- * Just like {@link Intent#getStringExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getStringExtra(String)} but doesn't throw exceptions. */
public static String safeGetStringExtra(Intent intent, String name) {
try {
return intent.getStringExtra(name);
@@ -193,9 +164,7 @@
}
}
- /**
- * Just like {@link Bundle#getString(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Bundle#getString(String)} but doesn't throw exceptions. */
public static String safeGetString(Bundle bundle, String name) {
try {
return bundle.getString(name);
@@ -206,9 +175,7 @@
}
}
- /**
- * Just like {@link Intent#getBundleExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getBundleExtra(String)} but doesn't throw exceptions. */
public static Bundle safeGetBundleExtra(Intent intent, String name) {
try {
return intent.getBundleExtra(name);
@@ -219,9 +186,7 @@
}
}
- /**
- * Just like {@link Bundle#getBundle(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Bundle#getBundle(String)} but doesn't throw exceptions. */
public static Bundle safeGetBundle(Bundle bundle, String name) {
try {
return bundle.getBundle(name);
@@ -232,9 +197,7 @@
}
}
- /**
- * Just like {@link Bundle#getParcelable(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Bundle#getParcelable(String)} but doesn't throw exceptions. */
public static <T extends Parcelable> T safeGetParcelable(Bundle bundle, String name) {
try {
return bundle.getParcelable(name);
@@ -245,9 +208,7 @@
}
}
- /**
- * Just like {@link Intent#getParcelableExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getParcelableExtra(String)} but doesn't throw exceptions. */
public static <T extends Parcelable> T safeGetParcelableExtra(Intent intent, String name) {
try {
return intent.getParcelableExtra(name);
@@ -272,9 +233,7 @@
}
}
- /**
- * Just link {@link Bundle#getParcelableArrayList(String)} but doesn't throw exceptions.
- */
+ /** Just link {@link Bundle#getParcelableArrayList(String)} but doesn't throw exceptions. */
public static <T extends Parcelable> ArrayList<T> safeGetParcelableArrayList(
Bundle bundle, String name) {
try {
@@ -286,9 +245,7 @@
}
}
- /**
- * Just like {@link Intent#getParcelableArrayExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getParcelableArrayExtra(String)} but doesn't throw exceptions. */
public static Parcelable[] safeGetParcelableArrayExtra(Intent intent, String name) {
try {
return intent.getParcelableArrayExtra(name);
@@ -298,9 +255,7 @@
}
}
- /**
- * Just like {@link Intent#getStringArrayListExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getStringArrayListExtra(String)} but doesn't throw exceptions. */
public static ArrayList<String> safeGetStringArrayListExtra(Intent intent, String name) {
try {
return intent.getStringArrayListExtra(name);
@@ -311,9 +266,7 @@
}
}
- /**
- * Just like {@link Intent#getByteArrayExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getByteArrayExtra(String)} but doesn't throw exceptions. */
public static byte[] safeGetByteArrayExtra(Intent intent, String name) {
try {
return intent.getByteArrayExtra(name);
@@ -324,9 +277,7 @@
}
}
- /**
- * Just like {@link Intent#getSerializableExtra(String)} but doesn't throw exceptions.
- */
+ /** Just like {@link Intent#getSerializableExtra(String)} but doesn't throw exceptions. */
@SuppressWarnings("unchecked")
public static <T extends Serializable> T safeGetSerializableExtra(Intent intent, String name) {
try {
@@ -479,7 +430,8 @@
* @return True if the intent is a MAIN intent a launcher would send.
*/
public static boolean isMainIntentFromLauncher(Intent intent) {
- return intent != null && TextUtils.equals(intent.getAction(), Intent.ACTION_MAIN)
+ return intent != null
+ && TextUtils.equals(intent.getAction(), Intent.ACTION_MAIN)
&& intent.hasCategory(Intent.CATEGORY_LAUNCHER)
&& 0 == (intent.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
}
@@ -512,8 +464,9 @@
boolean hasPackage = !TextUtils.isEmpty(intent.getPackage());
boolean matchesPackage = hasPackage && context.getPackageName().equals(intent.getPackage());
boolean hasComponent = intent.getComponent() != null;
- boolean matchesComponent = hasComponent
- && context.getPackageName().equals(intent.getComponent().getPackageName());
+ boolean matchesComponent =
+ hasComponent
+ && context.getPackageName().equals(intent.getComponent().getPackageName());
// Component takes precedence over PackageName when routing Intents if both are set, but to
// be on the safe side, ensure that if we have both package and component set, that they
diff --git a/base/android/java/src/org/chromium/base/JNIUtils.java b/base/android/java/src/org/chromium/base/JNIUtils.java
index c38d578..1864ef0 100644
--- a/base/android/java/src/org/chromium/base/JNIUtils.java
+++ b/base/android/java/src/org/chromium/base/JNIUtils.java
@@ -8,9 +8,7 @@
import java.util.Map;
-/**
- * This class provides JNI-related methods to the native library.
- */
+/** This class provides JNI-related methods to the native library. */
public class JNIUtils {
private static final String TAG = "JNIUtils";
private static ClassLoader sJniClassLoader;
@@ -48,9 +46,7 @@
sJniClassLoader = classLoader;
}
- /**
- * Helper to convert from java maps to two arrays for JNI.
- */
+ /** Helper to convert from java maps to two arrays for JNI. */
public static <K, V> void splitMap(Map<K, V> map, K[] outKeys, V[] outValues) {
assert map.size() == outKeys.length;
assert outValues.length == outKeys.length;
diff --git a/base/android/java/src/org/chromium/base/JavaExceptionReporter.java b/base/android/java/src/org/chromium/base/JavaExceptionReporter.java
index babdee9..91b82d5 100644
--- a/base/android/java/src/org/chromium/base/JavaExceptionReporter.java
+++ b/base/android/java/src/org/chromium/base/JavaExceptionReporter.java
@@ -59,8 +59,8 @@
@UiThread
public static void reportStackTrace(String stackTrace) {
assert ThreadUtils.runningOnUiThread();
- JavaExceptionReporterJni.get().reportJavaStackTrace(
- PiiElider.sanitizeStacktrace(stackTrace));
+ JavaExceptionReporterJni.get()
+ .reportJavaStackTrace(PiiElider.sanitizeStacktrace(stackTrace));
}
/**
@@ -78,13 +78,15 @@
@CalledByNative
private static void installHandler(boolean crashAfterReport) {
- Thread.setDefaultUncaughtExceptionHandler(new JavaExceptionReporter(
- Thread.getDefaultUncaughtExceptionHandler(), crashAfterReport));
+ Thread.setDefaultUncaughtExceptionHandler(
+ new JavaExceptionReporter(
+ Thread.getDefaultUncaughtExceptionHandler(), crashAfterReport));
}
@NativeMethods
interface Natives {
void reportJavaException(boolean crashAfterReport, Throwable e);
+
void reportJavaStackTrace(String stackTrace);
}
}
diff --git a/base/android/java/src/org/chromium/base/JavaHandlerThread.java b/base/android/java/src/org/chromium/base/JavaHandlerThread.java
index acb6bd0..cf2b95d 100644
--- a/base/android/java/src/org/chromium/base/JavaHandlerThread.java
+++ b/base/android/java/src/org/chromium/base/JavaHandlerThread.java
@@ -14,9 +14,7 @@
import java.lang.Thread.UncaughtExceptionHandler;
-/**
- * Thread in Java with an Android Handler. This class is not thread safe.
- */
+/** Thread in Java with an Android Handler. This class is not thread safe. */
@JNINamespace("base::android")
public class JavaHandlerThread {
private final HandlerThread mThread;
@@ -49,24 +47,29 @@
@CalledByNative
private void startAndInitialize(final long nativeThread, final long nativeEvent) {
maybeStart();
- new Handler(mThread.getLooper()).post(new Runnable() {
- @Override
- public void run() {
- JavaHandlerThreadJni.get().initializeThread(nativeThread, nativeEvent);
- }
- });
+ new Handler(mThread.getLooper())
+ .post(
+ new Runnable() {
+ @Override
+ public void run() {
+ JavaHandlerThreadJni.get()
+ .initializeThread(nativeThread, nativeEvent);
+ }
+ });
}
@CalledByNative
private void quitThreadSafely(final long nativeThread) {
// Allow pending java tasks to run, but don't run any delayed or newly queued up tasks.
- new Handler(mThread.getLooper()).post(new Runnable() {
- @Override
- public void run() {
- mThread.quit();
- JavaHandlerThreadJni.get().onLooperStopped(nativeThread);
- }
- });
+ new Handler(mThread.getLooper())
+ .post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mThread.quit();
+ JavaHandlerThreadJni.get().onLooperStopped(nativeThread);
+ }
+ });
// Signal that new tasks queued up won't be run.
mThread.getLooper().quitSafely();
}
@@ -97,12 +100,13 @@
// it generates crash dumps and kills the process.
@CalledByNative
private void listenForUncaughtExceptionsForTesting() {
- mThread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread t, Throwable e) {
- mUnhandledException = e;
- }
- });
+ mThread.setUncaughtExceptionHandler(
+ new UncaughtExceptionHandler() {
+ @Override
+ public void uncaughtException(Thread t, Throwable e) {
+ mUnhandledException = e;
+ }
+ });
}
@CalledByNative
@@ -113,6 +117,7 @@
@NativeMethods
interface Natives {
void initializeThread(long nativeJavaHandlerThread, long nativeEvent);
+
void onLooperStopped(long nativeJavaHandlerThread);
}
}
diff --git a/base/android/java/src/org/chromium/base/JniAndroid.java b/base/android/java/src/org/chromium/base/JniAndroid.java
index d4fcd72..7e07f8c 100644
--- a/base/android/java/src/org/chromium/base/JniAndroid.java
+++ b/base/android/java/src/org/chromium/base/JniAndroid.java
@@ -14,7 +14,7 @@
/**
* Returns a sanitized stacktrace (per {@link PiiElider#sanitizeStacktrace(String)}) for the
- * given throwable, for the purposes of uncaught exception handling.
+ * given throwable. Returns null if an OutOfMemoryError occurs.
*
* <p>Since this is running inside an uncaught exception handler, this method will make every
* effort not to throw; instead, any failures will be surfaced through the returned string.
@@ -23,9 +23,15 @@
private static String sanitizedStacktraceForUnhandledException(Throwable throwable) {
try {
return PiiElider.sanitizeStacktrace(Log.getStackTraceString(throwable));
+ } catch (OutOfMemoryError oomError) {
+ return null;
} catch (Throwable stacktraceThrowable) {
- return "Error while getting stack trace: "
- + Log.getStackTraceString(stacktraceThrowable);
+ try {
+ return "Error while getting stack trace: "
+ + Log.getStackTraceString(stacktraceThrowable);
+ } catch (OutOfMemoryError oomError) {
+ return null;
+ }
}
}
@@ -61,48 +67,52 @@
* @param throwable The uncaught Java exception that was thrown by a Java method called via JNI.
* @param nativeStackTrace The stack trace of the native code that called the Java method that
* threw.
+ * @return null, unless the uncaught exception handler threw an exception other than
+ * OutOfMemoryError exception, in which case that exception is returned.
*/
@CalledByNative
- private static void handleException(Throwable throwable, String nativeStackTrace) {
- // Try to make sure the exception details at least make their way to the log even if the
- // rest of this method goes horribly wrong.
- Log.e(TAG, "Handling uncaught Java exception", throwable);
-
- // Wrap the original exception so that we can annotate it with native stack information,
- // with the goal of including as much information in the Java crash report as possible.
- // (The native caller might itself have been called from Java. We don't need to care about
- // that because the stack trace in `throwable` includes the *entire* Java stack of the
- // current thread, even if there are native calls in the middle.)
- throwable = new UncaughtExceptionException(nativeStackTrace, throwable);
-
- // The Chromium JNI framework does not support resuming execution after a Java method called
- // through JNI throws an exception - we have to terminate the process at some point,
- // otherwise undefined behavior may result. The goal here is to provide as much useful
- // information to the crash handler as we can.
- //
- // To that end, we try to call the global uncaught exception handler. Hopefully that will
- // eventually reach the default Android uncaught exception handler (possibly going through
- // JavaExceptionReporter first, if we set one up), which will terminate the process. If for
- // any reason that doesn't happen (e.g. the app set up a different handler), then we just
- // give up and return - the native code we're returning to will terminate the process for
- // us. (Note that, even then, there is still a case where we might not terminate the
- // process: if the uncaught exception handler deliberately terminates the current thread but
- // not the entire process. This is very contrived though, and protecting against this would
- // be complicated, so we don't even try.)
- //
- // Log profusely along the way so that someone looking at the system log can easily
- // reconstruct the above sequence of events.
- Throwable handlerThrowable = null;
+ private static Throwable handleException(Throwable throwable, String nativeStackTrace) {
try {
+ // Try to make sure the exception details at least make their way to the log even if the
+ // rest of this method goes horribly wrong.
+ Log.e(TAG, "Handling uncaught Java exception", throwable);
+
+ // Wrap the original exception so that we can annotate it with native stack information,
+ // with the goal of including as much information in the Java crash report as possible.
+ // (The native caller might itself have been called from Java. We don't need to care
+ // about that because the stack trace in `throwable` includes the *entire* Java stack of
+ // the current thread, even if there are native calls in the middle.)
+ var wrappedThrowable = new UncaughtExceptionException(nativeStackTrace, throwable);
+
+ // The Chromium JNI framework does not support resuming execution after a Java method
+ // called through JNI throws an exception - we have to terminate the process at some
+ // point, otherwise undefined behavior may result. The goal here is to provide as much
+ // useful information to the crash handler as we can.
+ //
+ // To that end, we try to call the global uncaught exception handler. Hopefully that
+ // will eventually reach the default Android uncaught exception handler (possibly going
+ // through JavaExceptionReporter first, if we set one up), which will terminate the
+ // process. If for any reason that doesn't happen (e.g. the app set up a different
+ // handler), then we just give up and return the new exception (if any) - the native
+ // code we're returning to will terminate the process for us. (Note that, even then,
+ // there is still a case where we might not terminate the process: if the uncaught
+ // exception handler deliberately terminates the current thread but not the entire
+ // process. This is very contrived though, and protecting against this would be
+ // complicated, so we don't even try.)
Thread.getDefaultUncaughtExceptionHandler()
- .uncaughtException(Thread.currentThread(), throwable);
+ .uncaughtException(Thread.currentThread(), wrappedThrowable);
+ Log.e(TAG, "Global uncaught exception handler did not terminate the process.");
+ return null;
+ } catch (OutOfMemoryError e) {
+ // Don't call Log.e() so as to not risk throwing again.
+ return null;
} catch (Throwable e) {
- handlerThrowable = e;
+ // Log the new crash rather than the original crash, since if there is a bug in our
+ // crash handling logic, we need to know about it. If there is a crash in a webview
+ // app's crash handling logic, then we can rely on other apps to upload the underlying
+ // exception.
+ Log.e(TAG, "Exception in uncaught exception handler.", e);
+ return e;
}
- Log.e(
- TAG,
- "Global uncaught exception handler did not terminate the process - letting "
- + "native code terminate the process instead",
- handlerThrowable);
}
}
diff --git a/base/android/java/src/org/chromium/base/LifetimeAssert.java b/base/android/java/src/org/chromium/base/LifetimeAssert.java
index cbaf2ed..e56f1db 100644
--- a/base/android/java/src/org/chromium/base/LifetimeAssert.java
+++ b/base/android/java/src/org/chromium/base/LifetimeAssert.java
@@ -37,18 +37,14 @@
void onCleaned(WrappedReference ref, String msg);
}
- /**
- * Thrown for failed assertions.
- */
+ /** Thrown for failed assertions. */
static class LifetimeAssertException extends RuntimeException {
LifetimeAssertException(String msg, Throwable causedBy) {
super(msg, causedBy);
}
}
- /**
- * For capturing where objects were created.
- */
+ /** For capturing where objects were created. */
private static class CreationException extends RuntimeException {
CreationException() {
super("vvv This is where object was created. vvv");
@@ -58,8 +54,7 @@
// Used only for unit test.
static TestHook sTestHook;
- @VisibleForTesting
- final WrappedReference mWrapper;
+ @VisibleForTesting final WrappedReference mWrapper;
private final Object mTarget;
@@ -101,10 +96,12 @@
continue;
}
if (!wrapper.mSafeToGc) {
- String msg = String.format(
- "Object of type %s was GC'ed without cleanup. Refer to "
- + "\"Caused by\" for where object was created.",
- wrapper.mTargetClass.getName());
+ String msg =
+ String.format(
+ "Object of type %s was GC'ed without cleanup. Refer"
+ + " to \"Caused by\" for where object was"
+ + " created.",
+ wrapper.mTargetClass.getName());
if (sTestHook != null) {
sTestHook.onCleaned(wrapper, msg);
} else {
@@ -173,10 +170,12 @@
try {
for (WrappedReference ref : WrappedReference.sActiveWrappers) {
if (!ref.mSafeToGc) {
- String msg = String.format(
- "Object of type %s was not destroyed after test completed. "
- + "Refer to \"Caused by\" for where object was created.",
- ref.mTargetClass.getName());
+ String msg =
+ String.format(
+ "Object of type %s was not destroyed after test completed."
+ + " Refer to \"Caused by\" for where object was"
+ + " created.",
+ ref.mTargetClass.getName());
throw new LifetimeAssertException(msg, ref.mCreationException);
}
}
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java
index a56ad5e..81a36a6 100644
--- a/base/android/java/src/org/chromium/base/LocaleUtils.java
+++ b/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -18,15 +18,10 @@
import java.util.ArrayList;
import java.util.Locale;
-/**
- * This class provides the locale related methods.
- */
+/** This class provides the locale related methods. */
public class LocaleUtils {
- /**
- * Guards this class from being instantiated.
- */
- private LocaleUtils() {
- }
+ /** Guards this class from being instantiated. */
+ private LocaleUtils() {}
/**
* Java keeps deprecated language codes for Hebrew, Yiddish and Indonesian but Chromium uses
@@ -255,15 +250,14 @@
}
}
- /**
- * Helper class for N only code that is not validated on pre-N devices.
- */
+ /** Helper class for N only code that is not validated on pre-N devices. */
@RequiresApi(Build.VERSION_CODES.N)
@VisibleForTesting
static class ApisN {
static void setConfigLocales(Context base, Configuration config, String language) {
- LocaleList updatedLocales = prependToLocaleList(
- language, base.getResources().getConfiguration().getLocales());
+ LocaleList updatedLocales =
+ prependToLocaleList(
+ language, base.getResources().getConfiguration().getLocales());
config.setLocales(updatedLocales);
}
diff --git a/base/android/java/src/org/chromium/base/Log.java b/base/android/java/src/org/chromium/base/Log.java
index 0f18214..eaf9e8c 100644
--- a/base/android/java/src/org/chromium/base/Log.java
+++ b/base/android/java/src/org/chromium/base/Log.java
@@ -166,14 +166,17 @@
public static void i(String tag, String message) {
android.util.Log.i(normalizeTag(tag), message);
}
+
@AlwaysInline
public static void i(String tag, String message, Throwable t) {
android.util.Log.i(normalizeTag(tag), message, t);
}
+
@DoNotInline
public static void i(String tag, String messageTemplate, Object o) {
i(tag, messageTemplate, new Object[] {o});
}
+
@DoNotInline
public static void i(String tag, String messageTemplate, Object o1, Object o2) {
i(tag, messageTemplate, new Object[] {o1, o2});
@@ -205,14 +208,17 @@
public static void w(String tag, String message) {
android.util.Log.w(normalizeTag(tag), message);
}
+
@AlwaysInline
public static void w(String tag, String message, Throwable t) {
android.util.Log.w(normalizeTag(tag), message, t);
}
+
@DoNotInline
public static void w(String tag, String messageTemplate, Object o) {
w(tag, messageTemplate, new Object[] {o});
}
+
@DoNotInline
public static void w(String tag, String messageTemplate, Object o1, Object o2) {
w(tag, messageTemplate, new Object[] {o1, o2});
@@ -244,14 +250,17 @@
public static void e(String tag, String message) {
android.util.Log.e(normalizeTag(tag), message);
}
+
@AlwaysInline
public static void e(String tag, String message, Throwable t) {
android.util.Log.e(normalizeTag(tag), message, t);
}
+
@DoNotInline
public static void e(String tag, String messageTemplate, Object o) {
e(tag, messageTemplate, new Object[] {o});
}
+
@DoNotInline
public static void e(String tag, String messageTemplate, Object o1, Object o2) {
e(tag, messageTemplate, new Object[] {o1, o2});
diff --git a/base/android/java/src/org/chromium/base/MathUtils.java b/base/android/java/src/org/chromium/base/MathUtils.java
index 589a17e..7a2104c 100644
--- a/base/android/java/src/org/chromium/base/MathUtils.java
+++ b/base/android/java/src/org/chromium/base/MathUtils.java
@@ -4,9 +4,7 @@
package org.chromium.base;
-/**
- * Contains various math utilities used throughout Chrome Mobile.
- */
+/** Contains various math utilities used throughout Chrome Mobile. */
public class MathUtils {
/** A minimum difference to use when comparing floats for equality. */
public static final float EPSILON = 0.001f;
@@ -119,7 +117,7 @@
if (dimensions.length < 2 || dimensions[0] <= 0 || dimensions[1] <= 0) {
throw new IllegalArgumentException(
"Expected dimensions to have length >= 2 && dimensions[0] > 0 && "
- + "dimensions[1] > 0");
+ + "dimensions[1] > 0");
}
float scale =
Math.max((float) targetWidth / dimensions[0], (float) targetHeight / dimensions[1]);
@@ -175,6 +173,13 @@
}
/**
+ * Compute the distance given two coordinate vectors
+ */
+ public static float distance(float distanceX, float distanceY) {
+ return (float) Math.sqrt(distanceX * distanceX + distanceY * distanceY);
+ }
+
+ /**
* Maps {@code value} in [{@code fromStart}, {@code fromStop}] to
* [{@code toStart}, {@code toStop}].
*
diff --git a/base/android/java/src/org/chromium/base/MemoryPressureListener.java b/base/android/java/src/org/chromium/base/MemoryPressureListener.java
index 6fa06ef..1015ae9 100644
--- a/base/android/java/src/org/chromium/base/MemoryPressureListener.java
+++ b/base/android/java/src/org/chromium/base/MemoryPressureListener.java
@@ -54,9 +54,7 @@
private static ObserverList<MemoryPressureCallback> sCallbacks;
- /**
- * Called by the native side to add native callback.
- */
+ /** Called by the native side to add native callback. */
@CalledByNative
private static void addNativeCallback() {
ThreadUtils.assertOnUiThread();
@@ -111,8 +109,8 @@
} else if (ACTION_TRIM_MEMORY.equals(action)) {
simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_COMPLETE);
} else if (ACTION_TRIM_MEMORY_RUNNING_CRITICAL.equals(action)) {
- simulateTrimMemoryPressureSignal(activity,
- ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL);
+ simulateTrimMemoryPressureSignal(
+ activity, ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL);
} else if (ACTION_TRIM_MEMORY_MODERATE.equals(action)) {
simulateTrimMemoryPressureSignal(activity, ComponentCallbacks2.TRIM_MEMORY_MODERATE);
} else {
diff --git a/base/android/java/src/org/chromium/base/MutableFlagWithSafeDefault.java b/base/android/java/src/org/chromium/base/MutableFlagWithSafeDefault.java
new file mode 100644
index 0000000..0927cb7
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/MutableFlagWithSafeDefault.java
@@ -0,0 +1,47 @@
+// Copyright 2022 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+/**
+ * Flags of this type are un-cached flags that may be called before native,
+ * but not primarily. They have good default values to use before native is loaded,
+ * and will switch to using the native value once native is loaded.
+ * These flags replace code like:
+ * if (FeatureList.isInitialized() && SomeFeatureMap.isEnabled(featureName))
+ * or
+ * if (!FeatureList.isInitialized() || SomeFeatureMap.isEnabled(featureName)).
+ */
+public class MutableFlagWithSafeDefault extends Flag {
+ private final boolean mDefaultValue;
+ private final FeatureMap mFeatureMap;
+ private Boolean mInMemoryCachedValue;
+
+ public MutableFlagWithSafeDefault(
+ FeatureMap featureMap, String featureName, boolean defaultValue) {
+ super(featureName);
+ mFeatureMap = featureMap;
+ mDefaultValue = defaultValue;
+ }
+
+ @Override
+ public boolean isEnabled() {
+ if (mInMemoryCachedValue != null) return mInMemoryCachedValue;
+ if (FeatureList.hasTestFeature(mFeatureName)) {
+ return mFeatureMap.isEnabledInNative(mFeatureName);
+ }
+
+ if (FeatureList.isNativeInitialized()) {
+ mInMemoryCachedValue = mFeatureMap.isEnabledInNative(mFeatureName);
+ return mInMemoryCachedValue;
+ }
+
+ return mDefaultValue;
+ }
+
+ @Override
+ protected void clearInMemoryCachedValueForTesting() {
+ mInMemoryCachedValue = null;
+ }
+}
diff --git a/base/android/java/src/org/chromium/base/ObserverList.java b/base/android/java/src/org/chromium/base/ObserverList.java
index e801db6..1b383b3 100644
--- a/base/android/java/src/org/chromium/base/ObserverList.java
+++ b/base/android/java/src/org/chromium/base/ObserverList.java
@@ -30,9 +30,7 @@
*/
@NotThreadSafe
public class ObserverList<E> implements Iterable<E> {
- /**
- * Extended iterator interface that provides rewind functionality.
- */
+ /** Extended iterator interface that provides rewind functionality. */
public interface RewindableIterator<E> extends Iterator<E> {
/**
* Rewind the iterator back to the beginning.
@@ -168,9 +166,7 @@
return mCount;
}
- /**
- * Returns true if the ObserverList contains no observers.
- */
+ /** Returns true if the ObserverList contains no observers. */
public boolean isEmpty() {
if (mEnableThreadAsserts) mThreadChecker.assertOnValidThread();
diff --git a/base/android/java/src/org/chromium/base/PackageManagerUtils.java b/base/android/java/src/org/chromium/base/PackageManagerUtils.java
index 2d1661e..91d814c 100644
--- a/base/android/java/src/org/chromium/base/PackageManagerUtils.java
+++ b/base/android/java/src/org/chromium/base/PackageManagerUtils.java
@@ -13,19 +13,18 @@
import java.util.Collections;
import java.util.List;
-/**
- * This class provides Android PackageManager related utility methods.
- */
+/** This class provides Android PackageManager related utility methods. */
public class PackageManagerUtils {
private static final String TAG = "PackageManagerUtils";
// This is the intent Android uses internally to detect browser apps.
// See
// https://cs.android.com/android/_/android/platform/packages/modules/Permission/+/android12-release:PermissionController/src/com/android/permissioncontroller/role/model/BrowserRoleBehavior.java;drc=86fa7d5dfa43f66b170f93ade4f59b9a770be32f;l=50
- public static final Intent BROWSER_INTENT = new Intent()
- .setAction(Intent.ACTION_VIEW)
- .addCategory(Intent.CATEGORY_BROWSABLE)
- .setData(Uri.fromParts("http", "", null));
+ public static final Intent BROWSER_INTENT =
+ new Intent()
+ .setAction(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .setData(Uri.fromParts("http", "", null));
/**
* Retrieve information about the Activity that will handle the given Intent.
@@ -108,8 +107,11 @@
// Apparently MATCH_ALL doesn't include MATCH_DIRECT_BOOT_*.
// See
// https://cs.android.com/android/_/android/platform/packages/modules/Permission/+/android12-release:PermissionController/src/com/android/permissioncontroller/role/model/BrowserRoleBehavior.java;drc=86fa7d5dfa43f66b170f93ade4f59b9a770be32f;l=114
- int flags = PackageManager.MATCH_ALL | PackageManager.MATCH_DIRECT_BOOT_AWARE
- | PackageManager.MATCH_DIRECT_BOOT_UNAWARE | PackageManager.MATCH_DEFAULT_ONLY;
+ int flags =
+ PackageManager.MATCH_ALL
+ | PackageManager.MATCH_DIRECT_BOOT_AWARE
+ | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
+ | PackageManager.MATCH_DEFAULT_ONLY;
return queryIntentActivities(BROWSER_INTENT, flags);
}
diff --git a/base/android/java/src/org/chromium/base/PackageUtils.java b/base/android/java/src/org/chromium/base/PackageUtils.java
index 00f1378..23e8cf7 100644
--- a/base/android/java/src/org/chromium/base/PackageUtils.java
+++ b/base/android/java/src/org/chromium/base/PackageUtils.java
@@ -23,16 +23,12 @@
import java.util.ArrayList;
import java.util.List;
-/**
- * This class provides package checking related methods.
- */
+/** This class provides package checking related methods. */
public class PackageUtils {
private static final String TAG = "PackageUtils";
private static final char[] HEX_CHAR_LOOKUP = "0123456789ABCDEF".toCharArray();
- /**
- * Retrieves the PackageInfo for the given package, or null if it is not installed.
- */
+ /** Retrieves the PackageInfo for the given package, or null if it is not installed. */
public static @Nullable PackageInfo getPackageInfo(String packageName, int flags) {
PackageManager pm = ContextUtils.getApplicationContext().getPackageManager();
try {
@@ -69,9 +65,7 @@
return getPackageInfo(packageName, 0) != null;
}
- /**
- * Returns the PackageInfo for the current app, as retrieve by PackageManager.
- */
+ /** Returns the PackageInfo for the current app, as retrieve by PackageManager. */
public static PackageInfo getApplicationPackageInfo(int flags) {
PackageInfo ret = getPackageInfo(BuildInfo.getInstance().packageName, flags);
assert ret != null;
@@ -99,10 +93,12 @@
String hexString = null;
try {
X509Certificate certificate =
- (X509Certificate) CertificateFactory.getInstance("X509")
- .generateCertificate(input);
- hexString = byteArrayToHexString(
- MessageDigest.getInstance("SHA256").digest(certificate.getEncoded()));
+ (X509Certificate)
+ CertificateFactory.getInstance("X509").generateCertificate(input);
+ hexString =
+ byteArrayToHexString(
+ MessageDigest.getInstance("SHA256")
+ .digest(certificate.getEncoded()));
} catch (CertificateException | NoSuchAlgorithmException e) {
Log.w(TAG, "Exception", e);
return null;
diff --git a/base/android/java/src/org/chromium/base/PathService.java b/base/android/java/src/org/chromium/base/PathService.java
index f058e72..9683e4c 100644
--- a/base/android/java/src/org/chromium/base/PathService.java
+++ b/base/android/java/src/org/chromium/base/PathService.java
@@ -7,9 +7,7 @@
import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
-/**
- * This class provides java side access to the native PathService.
- */
+/** This class provides java side access to the native PathService. */
@JNINamespace("base::android")
public abstract class PathService {
diff --git a/base/android/java/src/org/chromium/base/PathUtils.java b/base/android/java/src/org/chromium/base/PathUtils.java
index b2910b7..c6e7041 100644
--- a/base/android/java/src/org/chromium/base/PathUtils.java
+++ b/base/android/java/src/org/chromium/base/PathUtils.java
@@ -31,9 +31,7 @@
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicBoolean;
-/**
- * This class provides the path related methods for the native library.
- */
+/** This class provides the path related methods for the native library. */
public abstract class PathUtils {
private static final String TAG = "PathUtils";
private static final String THUMBNAIL_DIRECTORY_NAME = "textures";
@@ -176,13 +174,13 @@
AsyncTask.THREAD_POOL_EXECUTOR.execute(sDirPathFetchTask);
} else {
assert TextUtils.equals(sDataDirectoryBasePath, dataBasePath)
- : String.format("%s != %s", dataBasePath, sDataDirectoryBasePath);
+ : String.format("%s != %s", dataBasePath, sDataDirectoryBasePath);
assert TextUtils.equals(sCacheDirectoryBasePath, cacheBasePath)
- : String.format("%s != %s", cacheBasePath, sCacheDirectoryBasePath);
+ : String.format("%s != %s", cacheBasePath, sCacheDirectoryBasePath);
assert TextUtils.equals(sDataDirectorySuffix, dataDirSuffix)
- : String.format("%s != %s", dataDirSuffix, sDataDirectorySuffix);
+ : String.format("%s != %s", dataDirSuffix, sDataDirectorySuffix);
assert TextUtils.equals(sCacheSubDirectory, cacheSubDir)
- : String.format("%s != %s", cacheSubDir, sCacheSubDirectory);
+ : String.format("%s != %s", cacheSubDir, sCacheSubDirectory);
}
}
@@ -199,7 +197,6 @@
* @param cacheSubDir The subdirectory in the cache directory to use, if non-null.
* @see Context#getDir(String, int)
*/
-
public static void setPrivateDataDirectorySuffix(String suffix, String cacheSubDir) {
setPrivateDirectoryPath(null, null, suffix, cacheSubDir);
}
@@ -278,8 +275,9 @@
public static @NonNull String[] getAllPrivateDownloadsDirectories() {
List<File> files = new ArrayList<>();
try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
- File[] externalDirs = ContextUtils.getApplicationContext().getExternalFilesDirs(
- Environment.DIRECTORY_DOWNLOADS);
+ File[] externalDirs =
+ ContextUtils.getApplicationContext()
+ .getExternalFilesDirs(Environment.DIRECTORY_DOWNLOADS);
files = (externalDirs == null) ? files : Arrays.asList(externalDirs);
}
return toAbsolutePathStrings(files);
@@ -299,16 +297,20 @@
ApiHelperForQ.getExternalVolumeNames(ContextUtils.getApplicationContext());
for (String vol : volumes) {
if (!TextUtils.isEmpty(vol) && !vol.contains(MediaStore.VOLUME_EXTERNAL_PRIMARY)) {
- StorageManager manager = ApiHelperForM.getSystemService(
- ContextUtils.getApplicationContext(), StorageManager.class);
+ StorageManager manager =
+ ApiHelperForM.getSystemService(
+ ContextUtils.getApplicationContext(), StorageManager.class);
File volumeDir =
ApiHelperForR.getVolumeDir(manager, MediaStore.Files.getContentUri(vol));
File volumeDownloadDir = new File(volumeDir, Environment.DIRECTORY_DOWNLOADS);
// Happens in rare case when Android doesn't create the download directory for this
// volume.
if (!volumeDownloadDir.isDirectory()) {
- Log.w(TAG, "Download dir missing: %s, parent dir:%s, isDirectory:%s",
- volumeDownloadDir.getAbsolutePath(), volumeDir.getAbsolutePath(),
+ Log.w(
+ TAG,
+ "Download dir missing: %s, parent dir:%s, isDirectory:%s",
+ volumeDownloadDir.getAbsolutePath(),
+ volumeDir.getAbsolutePath(),
volumeDir.isDirectory());
}
files.add(volumeDownloadDir);
diff --git a/base/android/java/src/org/chromium/base/PiiElider.java b/base/android/java/src/org/chromium/base/PiiElider.java
index 28fbdb8..ebfb2f8 100644
--- a/base/android/java/src/org/chromium/base/PiiElider.java
+++ b/base/android/java/src/org/chromium/base/PiiElider.java
@@ -10,9 +10,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * Provides public methods for detecting and eliding sensitive PII.
- */
+/** Provides public methods for detecting and eliding sensitive PII. */
public class PiiElider {
private static final String EMAIL_ELISION = "XXX@EMAIL.ELIDED";
@@ -22,9 +20,9 @@
private static final String IP_ADDRESS =
"((25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9])\\.(25[0-5]|2[0-4]"
- + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
- + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
- + "|[1-9][0-9]|[0-9]))";
+ + "[0-9]|[0-1][0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]"
+ + "[0-9]{2}|[1-9][0-9]|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1][0-9]{2}"
+ + "|[1-9][0-9]|[0-9]))";
private static final String IRI =
"[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
@@ -41,8 +39,13 @@
// Either a single valid path component character or a URI-encoded character.
"(([" + GOOD_IRI_CHAR + ";/?:@&=#~.+!*'(),_-])|" + URI_ENCODED_CHAR + ")";
- private static final String URI_SCHEME = "((http|https|Http|Https|rtsp|Rtsp)://"
- + "(" + URI_CHAR + "{1,64}(:" + URI_CHAR + "{1,25})?@)?)";
+ private static final String URI_SCHEME =
+ "((http|https|Http|Https|rtsp|Rtsp)://"
+ + "("
+ + URI_CHAR
+ + "{1,64}(:"
+ + URI_CHAR
+ + "{1,25})?@)?)";
private static final String DOMAIN_NAME = "(" + HOST_NAME + "|" + IP_ADDRESS + ")";
@@ -62,25 +65,33 @@
"(" + URL_WITH_OPTIONAL_SCHEME_AND_PORT + "|" + INTENT + ")";
private static final Pattern WEB_URL =
- Pattern.compile("(\\b|^)" // Always start on a word boundary or start of string.
- + "(" + URL_OR_INTENT + ")" // Main URL or Intent scheme/domain/root path.
- + "(/" + PATH_CHAR + "*)?" // Rest of the URI path.
- + "(\\b|$)"); // Always end on a word boundary or end of string.
+ Pattern.compile(
+ "(\\b|^)" // Always start on a word boundary or start of string.
+ + "("
+ + URL_OR_INTENT
+ + ")" // Main URL or Intent scheme/domain/root path.
+ + "(/"
+ + PATH_CHAR
+ + "*)?" // Rest of the URI path.
+ + "(\\b|$)"); // Always end on a word boundary or end of string.
// Example variant info chromium-TrichromeChromeGoogle6432.aab
private static final String CHROME_VARIANT_INFO = "chromium-[^\\.]+\\.aab";
- private static final Pattern LIKELY_EXCEPTION_LOG = Pattern.compile("\\sat\\s"
- // These are all package prefixes of classes that are likely to
- // exist on a stacktrace and are very unlikely to be a PII url.
- + "(org\\.chromium|com\\.google|java|android|com\\.android)\\.[^ ]+.|"
- // if a line has what looks like line number info, it's probably an
- // exception log.
- + "\\(" + CHROME_VARIANT_INFO
- + "[^:]+:\\d+\\)|"
- // When a class is not found it can fail to satisfy our isClass
- // check but is still worth noting what it was.
- + "Caused by: java\\.lang\\."
- + "(ClassNotFoundException|NoClassDefFoundError):");
+ private static final Pattern LIKELY_EXCEPTION_LOG =
+ Pattern.compile(
+ "\\sat\\s"
+ // These are all package prefixes of classes that are likely to
+ // exist on a stacktrace and are very unlikely to be a PII url.
+ + "(org\\.chromium|com\\.google|java|android|com\\.android)\\.[^ ]+.|"
+ // if a line has what looks like line number info, it's probably an
+ // exception log.
+ + "\\("
+ + CHROME_VARIANT_INFO
+ + "[^:]+:\\d+\\)|"
+ // When a class is not found it can fail to satisfy our isClass
+ // check but is still worth noting what it was.
+ + "Caused by: java\\.lang\\."
+ + "(ClassNotFoundException|NoClassDefFoundError):");
private static final String IP_ELISION = "1.2.3.4";
private static final String MAC_ELISION = "01:23:45:67:89:AB";
@@ -95,8 +106,19 @@
new String[] {"org.chromium.", "com.google.", "com.chrome."};
private static final String[] SYSTEM_NAMESPACE =
- new String[] {"android.", "com.android.", "dalvik.", "java.", "javax.", "org.apache.",
- "org.json.", "org.w3c.dom.", "org.xml.", "org.xmlpull.", "System."};
+ new String[] {
+ "android.",
+ "com.android.",
+ "dalvik.",
+ "java.",
+ "javax.",
+ "org.apache.",
+ "org.json.",
+ "org.w3c.dom.",
+ "org.xml.",
+ "org.xmlpull.",
+ "System."
+ };
/**
* Elides any emails in the specified {@link String} with
@@ -126,7 +148,8 @@
start = matcher.start();
int end = matcher.end();
String url = buffer.substring(start, end);
- if (!likelyToBeAppNamespace(url) && !likelyToBeSystemNamespace(url)
+ if (!likelyToBeAppNamespace(url)
+ && !likelyToBeSystemNamespace(url)
&& !likelyToBeClassOrMethodName(url)) {
buffer.replace(start, end, URL_ELISION);
end = start + URL_ELISION.length();
diff --git a/base/android/java/src/org/chromium/base/PowerMonitor.java b/base/android/java/src/org/chromium/base/PowerMonitor.java
index 6c61d9d..5865839 100644
--- a/base/android/java/src/org/chromium/base/PowerMonitor.java
+++ b/base/android/java/src/org/chromium/base/PowerMonitor.java
@@ -18,9 +18,7 @@
import org.chromium.base.compat.ApiHelperForQ;
-/**
- * Integrates native PowerMonitor with the java side.
- */
+/** Integrates native PowerMonitor with the java side. */
@JNINamespace("base::android")
public class PowerMonitor {
private static PowerMonitor sInstance;
@@ -34,9 +32,7 @@
sInstance = new PowerMonitor();
}
- /**
- * Create a PowerMonitor instance if none exists.
- */
+ /** Create a PowerMonitor instance if none exists. */
public static void create() {
ThreadUtils.assertOnUiThread();
@@ -58,13 +54,16 @@
IntentFilter powerConnectedFilter = new IntentFilter();
powerConnectedFilter.addAction(Intent.ACTION_POWER_CONNECTED);
powerConnectedFilter.addAction(Intent.ACTION_POWER_DISCONNECTED);
- ContextUtils.registerProtectedBroadcastReceiver(context, new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- PowerMonitor.onBatteryChargingChanged(
- intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED));
- }
- }, powerConnectedFilter);
+ ContextUtils.registerProtectedBroadcastReceiver(
+ context,
+ new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ PowerMonitor.onBatteryChargingChanged(
+ intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED));
+ }
+ },
+ powerConnectedFilter);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
PowerManager powerManager =
@@ -75,8 +74,7 @@
}
}
- private PowerMonitor() {
- }
+ private PowerMonitor() {}
private static void onBatteryChargingChanged(boolean isBatteryPower) {
assert sInstance != null;
@@ -105,8 +103,9 @@
}
private static int getRemainingBatteryCapacityImpl() {
- return ((BatteryManager) ContextUtils.getApplicationContext().getSystemService(
- Context.BATTERY_SERVICE))
+ return ((BatteryManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.BATTERY_SERVICE))
.getIntProperty(BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER);
}
@@ -121,8 +120,9 @@
if (sInstance == null) create();
PowerManager powerManager =
- (PowerManager) ContextUtils.getApplicationContext().getSystemService(
- Context.POWER_SERVICE);
+ (PowerManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.POWER_SERVICE);
if (powerManager == null) return -1;
return ApiHelperForQ.getCurrentThermalStatus(powerManager);
}
@@ -130,6 +130,7 @@
@NativeMethods
interface Natives {
void onBatteryChargingChanged();
+
void onThermalStatusChanged(int thermalStatus);
}
}
diff --git a/base/android/java/src/org/chromium/base/PowerMonitorForQ.java b/base/android/java/src/org/chromium/base/PowerMonitorForQ.java
index 7a1aebd..cebea1b 100644
--- a/base/android/java/src/org/chromium/base/PowerMonitorForQ.java
+++ b/base/android/java/src/org/chromium/base/PowerMonitorForQ.java
@@ -19,11 +19,12 @@
private PowerMonitorForQ() {}
public static void addThermalStatusListener(PowerManager powerManager) {
- powerManager.addThermalStatusListener(new PowerManager.OnThermalStatusChangedListener() {
- @Override
- public void onThermalStatusChanged(int status) {
- PowerMonitorJni.get().onThermalStatusChanged(status);
- }
- });
+ powerManager.addThermalStatusListener(
+ new PowerManager.OnThermalStatusChangedListener() {
+ @Override
+ public void onThermalStatusChanged(int status) {
+ PowerMonitorJni.get().onThermalStatusChanged(status);
+ }
+ });
}
}
diff --git a/base/android/java/src/org/chromium/base/Promise.java b/base/android/java/src/org/chromium/base/Promise.java
index 9244202..00bd162 100644
--- a/base/android/java/src/org/chromium/base/Promise.java
+++ b/base/android/java/src/org/chromium/base/Promise.java
@@ -30,8 +30,7 @@
int REJECTED = 2;
}
- @PromiseState
- private int mState = PromiseState.UNFULFILLED;
+ @PromiseState private int mState = PromiseState.UNFULFILLED;
private T mResult;
private final List<Callback<T>> mFulfillCallbacks = new LinkedList<>();
@@ -76,13 +75,15 @@
return;
}
- assert mRejectCallbacks.size() == 0 : "Do not call the single argument "
- + "Promise.then(Callback) on a Promise that already has a rejection handler.";
+ assert mRejectCallbacks.size() == 0
+ : "Do not call the single argument Promise.then(Callback) on a Promise that already"
+ + " has a rejection handler.";
- Callback<Exception> onReject = reason -> {
- throw new UnhandledRejectionException(
- "Promise was rejected without a rejection handler.", reason);
- };
+ Callback<Exception> onReject =
+ reason -> {
+ throw new UnhandledRejectionException(
+ "Promise was rejected without a rejection handler.", reason);
+ };
then(onFulfill, onReject);
mThrowingRejectionHandler = true;
@@ -123,8 +124,9 @@
}
private void exceptInner(Callback<Exception> onReject) {
- assert !mThrowingRejectionHandler : "Do not add an exception handler to a Promise you have "
- + "called the single argument Promise.then(Callback) on.";
+ assert !mThrowingRejectionHandler
+ : "Do not add an exception handler to a Promise you have "
+ + "called the single argument Promise.then(Callback) on.";
if (mState == PromiseState.REJECTED) {
postCallbackToLooper(onReject, mRejectReason);
@@ -146,14 +148,15 @@
// Once this Promise is fulfilled:
// - Apply the given function to the result.
// - Fulfill the new Promise.
- thenInner(result -> {
- try {
- promise.fulfill(function.apply(result));
- } catch (Exception e) {
- // If function application fails, reject the next Promise.
- promise.reject(e);
- }
- });
+ thenInner(
+ result -> {
+ try {
+ promise.fulfill(function.apply(result));
+ } catch (Exception e) {
+ // If function application fails, reject the next Promise.
+ promise.reject(e);
+ }
+ });
// If this Promise is rejected, reject the next Promise.
exceptInner(promise::reject);
@@ -175,16 +178,18 @@
// Once this Promise is fulfilled:
// - Apply the given function to the result (giving us an inner Promise).
// - On fulfillment of this inner Promise, fulfill our return Promise.
- thenInner(result -> {
- try {
- // When the inner Promise is fulfilled, fulfill the return Promise.
- // Alternatively, if the inner Promise is rejected, reject the return Promise.
- function.apply(result).then(promise::fulfill, promise::reject);
- } catch (Exception e) {
- // If creating the inner Promise failed, reject the next Promise.
- promise.reject(e);
- }
- });
+ thenInner(
+ result -> {
+ try {
+ // When the inner Promise is fulfilled, fulfill the return Promise.
+ // Alternatively, if the inner Promise is rejected, reject the return
+ // Promise.
+ function.apply(result).then(promise::fulfill, promise::reject);
+ } catch (Exception e) {
+ // If creating the inner Promise failed, reject the next Promise.
+ promise.reject(e);
+ }
+ });
// If this Promise is rejected, reject the next Promise.
exceptInner(promise::reject);
@@ -230,24 +235,18 @@
mRejectCallbacks.clear();
}
- /**
- * Rejects a Promise, see {@link #reject(Exception)}.
- */
+ /** Rejects a Promise, see {@link #reject(Exception)}. */
public void reject() {
reject(null);
}
- /**
- * Returns whether the promise is fulfilled.
- */
+ /** Returns whether the promise is fulfilled. */
public boolean isFulfilled() {
checkThread();
return mState == PromiseState.FULFILLED;
}
- /**
- * Returns whether the promise is rejected.
- */
+ /** Returns whether the promise is rejected. */
public boolean isRejected() {
checkThread();
return mState == PromiseState.REJECTED;
@@ -263,18 +262,14 @@
return mResult;
}
- /**
- * Convenience method to return a Promise fulfilled with the given result.
- */
+ /** Convenience method to return a Promise fulfilled with the given result. */
public static <T> Promise<T> fulfilled(T result) {
Promise<T> promise = new Promise<>();
promise.fulfill(result);
return promise;
}
- /**
- * Convenience method to return a rejected Promise.
- */
+ /** Convenience method to return a rejected Promise. */
public static <T> Promise<T> rejected() {
Promise<T> promise = new Promise<>();
promise.reject();
diff --git a/base/android/java/src/org/chromium/base/RadioUtils.java b/base/android/java/src/org/chromium/base/RadioUtils.java
index cbf4e27..fdf3019 100644
--- a/base/android/java/src/org/chromium/base/RadioUtils.java
+++ b/base/android/java/src/org/chromium/base/RadioUtils.java
@@ -23,9 +23,7 @@
import org.chromium.base.compat.ApiHelperForM;
import org.chromium.base.compat.ApiHelperForP;
-/**
- * Exposes radio related information about the current device.
- */
+/** Exposes radio related information about the current device. */
@JNINamespace("base::android")
public class RadioUtils {
// Cached value indicating if app has ACCESS_NETWORK_STATE permission.
@@ -42,7 +40,8 @@
*/
@CalledByNative
private static boolean isSupported() {
- return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && haveAccessNetworkState()
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P
+ && haveAccessNetworkState()
&& haveAccessWifiState();
}
@@ -51,10 +50,12 @@
// end in the same result so it's not a problem.
if (sHaveAccessNetworkState == null) {
sHaveAccessNetworkState =
- ApiCompatibilityUtils.checkPermission(ContextUtils.getApplicationContext(),
- Manifest.permission.ACCESS_NETWORK_STATE, Process.myPid(),
- Process.myUid())
- == PackageManager.PERMISSION_GRANTED;
+ ApiCompatibilityUtils.checkPermission(
+ ContextUtils.getApplicationContext(),
+ Manifest.permission.ACCESS_NETWORK_STATE,
+ Process.myPid(),
+ Process.myUid())
+ == PackageManager.PERMISSION_GRANTED;
}
return sHaveAccessNetworkState;
}
@@ -64,9 +65,12 @@
// end in the same result so it's not a problem.
if (sHaveAccessWifiState == null) {
sHaveAccessWifiState =
- ApiCompatibilityUtils.checkPermission(ContextUtils.getApplicationContext(),
- Manifest.permission.ACCESS_WIFI_STATE, Process.myPid(), Process.myUid())
- == PackageManager.PERMISSION_GRANTED;
+ ApiCompatibilityUtils.checkPermission(
+ ContextUtils.getApplicationContext(),
+ Manifest.permission.ACCESS_WIFI_STATE,
+ Process.myPid(),
+ Process.myUid())
+ == PackageManager.PERMISSION_GRANTED;
}
return sHaveAccessWifiState;
}
@@ -77,12 +81,14 @@
*/
@CalledByNative
@RequiresApi(Build.VERSION_CODES.P)
+ @SuppressWarnings("AssertionSideEffect") // isSupported() caches via sHaveAccessNetworkState.
private static boolean isWifiConnected() {
assert isSupported();
try (TraceEvent te = TraceEvent.scoped("RadioUtils::isWifiConnected")) {
ConnectivityManager connectivityManager =
- (ConnectivityManager) ContextUtils.getApplicationContext().getSystemService(
- Context.CONNECTIVITY_SERVICE);
+ (ConnectivityManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.CONNECTIVITY_SERVICE);
Network network = ApiHelperForM.getActiveNetwork(connectivityManager);
if (network == null) {
return false;
@@ -102,12 +108,14 @@
*/
@CalledByNative
@RequiresApi(Build.VERSION_CODES.P)
+ @SuppressWarnings("AssertionSideEffect") // isSupported() caches via sHaveAccessNetworkState.
private static int getCellSignalLevel() {
assert isSupported();
try (TraceEvent te = TraceEvent.scoped("RadioUtils::getCellSignalLevel")) {
TelephonyManager telephonyManager =
- (TelephonyManager) ContextUtils.getApplicationContext().getSystemService(
- Context.TELEPHONY_SERVICE);
+ (TelephonyManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.TELEPHONY_SERVICE);
int level = -1;
try {
SignalStrength signalStrength = ApiHelperForP.getSignalStrength(telephonyManager);
@@ -128,12 +136,14 @@
*/
@CalledByNative
@RequiresApi(Build.VERSION_CODES.P)
+ @SuppressWarnings("AssertionSideEffect") // isSupported() caches via sHaveAccessNetworkState.
private static int getCellDataActivity() {
assert isSupported();
try (TraceEvent te = TraceEvent.scoped("RadioUtils::getCellDataActivity")) {
TelephonyManager telephonyManager =
- (TelephonyManager) ContextUtils.getApplicationContext().getSystemService(
- Context.TELEPHONY_SERVICE);
+ (TelephonyManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.TELEPHONY_SERVICE);
try {
return telephonyManager.getDataActivity();
} catch (java.lang.SecurityException e) {
diff --git a/base/android/java/src/org/chromium/base/StreamUtil.java b/base/android/java/src/org/chromium/base/StreamUtil.java
index ec99afc..1b98c73 100644
--- a/base/android/java/src/org/chromium/base/StreamUtil.java
+++ b/base/android/java/src/org/chromium/base/StreamUtil.java
@@ -8,9 +8,7 @@
import java.io.IOException;
import java.util.zip.ZipFile;
-/**
- * Helper methods to deal with stream related tasks.
- */
+/** Helper methods to deal with stream related tasks. */
public class StreamUtil {
/**
* Handle closing a {@link java.io.Closeable} via {@link java.io.Closeable#close()} and catch
diff --git a/base/android/java/src/org/chromium/base/StrictModeContext.java b/base/android/java/src/org/chromium/base/StrictModeContext.java
index e7b91fe..a5655e7 100644
--- a/base/android/java/src/org/chromium/base/StrictModeContext.java
+++ b/base/android/java/src/org/chromium/base/StrictModeContext.java
@@ -68,9 +68,7 @@
}
}
- /**
- * Convenience method for disabling StrictMode for disk-writes with try-with-resources.
- */
+ /** Convenience method for disabling StrictMode for disk-writes with try-with-resources. */
public static StrictModeContext allowDiskWrites() {
try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowDiskWrites")) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
@@ -78,9 +76,7 @@
}
}
- /**
- * Convenience method for disabling StrictMode for disk-reads with try-with-resources.
- */
+ /** Convenience method for disabling StrictMode for disk-reads with try-with-resources. */
public static StrictModeContext allowDiskReads() {
try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowDiskReads")) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
@@ -88,9 +84,7 @@
}
}
- /**
- * Convenience method for disabling StrictMode for slow calls with try-with-resources.
- */
+ /** Convenience method for disabling StrictMode for slow calls with try-with-resources. */
public static StrictModeContext allowSlowCalls() {
try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowSlowCalls")) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
@@ -110,9 +104,10 @@
try (TraceEvent e = TraceEvent.scoped("StrictModeContext.allowUnbufferedIo")) {
StrictMode.ThreadPolicy oldPolicy = StrictMode.getThreadPolicy();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
- StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder(oldPolicy)
- .permitUnbufferedIo()
- .build());
+ StrictMode.setThreadPolicy(
+ new StrictMode.ThreadPolicy.Builder(oldPolicy)
+ .permitUnbufferedIo()
+ .build());
}
return new StrictModeContext(oldPolicy);
}
diff --git a/base/android/java/src/org/chromium/base/SysUtils.java b/base/android/java/src/org/chromium/base/SysUtils.java
index 47686b5..0034134 100644
--- a/base/android/java/src/org/chromium/base/SysUtils.java
+++ b/base/android/java/src/org/chromium/base/SysUtils.java
@@ -24,9 +24,7 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-/**
- * Exposes system related information about the current device.
- */
+/** Exposes system related information about the current device. */
@JNINamespace("base::android")
public class SysUtils {
// A device reporting strictly more total memory in megabytes cannot be considered 'low-end'.
@@ -44,7 +42,7 @@
private static Boolean sHighEndDiskDevice;
- private SysUtils() { }
+ private SysUtils() {}
/**
* Return the amount of physical memory on this device in kilobytes.
@@ -73,7 +71,7 @@
BufferedReader reader = new BufferedReader(fileReader);
try {
String line;
- for (;;) {
+ for (; ; ) {
line = reader.readLine();
if (line == null) {
Log.w(TAG, "/proc/meminfo lacks a MemTotal entry?");
@@ -136,8 +134,9 @@
@CalledByNative
public static boolean isCurrentlyLowMemory() {
ActivityManager am =
- (ActivityManager) ContextUtils.getApplicationContext().getSystemService(
- Context.ACTIVITY_SERVICE);
+ (ActivityManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.ACTIVITY_SERVICE);
ActivityManager.MemoryInfo info = new ActivityManager.MemoryInfo();
try {
am.getMemoryInfo(info);
diff --git a/base/android/java/src/org/chromium/base/ThreadUtils.java b/base/android/java/src/org/chromium/base/ThreadUtils.java
index 78a8662..d4fdbcf 100644
--- a/base/android/java/src/org/chromium/base/ThreadUtils.java
+++ b/base/android/java/src/org/chromium/base/ThreadUtils.java
@@ -17,9 +17,7 @@
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
-/**
- * Helper methods to deal with threading related tasks.
- */
+/** Helper methods to deal with threading related tasks. */
public class ThreadUtils {
private static final Object sLock = new Object();
@@ -47,20 +45,6 @@
* }
* }
* </pre>
- *
- * Another way to use this class is to also use the baked in support for destruction:
- * <pre>
- * {@code
- * class Foo {
- * // Valid thread is set during construction here.
- * private final ThreadChecker mThreadChecker = new ThreadChecker();
- *
- * public void doFoo() {
- * mThreadChecker.assertOnValidThreadAndState();
- * }
- * }
- * }
- * </pre>
*/
public static class ThreadChecker {
private final long mThreadId = Process.myTid();
@@ -70,8 +54,8 @@
* on.
*/
public void assertOnValidThread() {
- assert sThreadAssertsDisabledForTesting
- || mThreadId == Process.myTid() : "Must only be used on a single thread.";
+ assert sThreadAssertsDisabledForTesting || mThreadId == Process.myTid()
+ : "Must only be used on a single thread.";
}
}
@@ -99,9 +83,13 @@
// Must come after PostTask is initialized since it uses PostTask.
TraceEvent.onUiThreadReady();
} else if (sUiThreadHandler.getLooper() != looper) {
- throw new RuntimeException("UI thread looper is already set to "
- + sUiThreadHandler.getLooper() + " (Main thread looper is "
- + Looper.getMainLooper() + "), cannot set to new looper " + looper);
+ throw new RuntimeException(
+ "UI thread looper is already set to "
+ + sUiThreadHandler.getLooper()
+ + " (Main thread looper is "
+ + Looper.getMainLooper()
+ + "), cannot set to new looper "
+ + looper);
}
}
}
@@ -286,9 +274,7 @@
return getUiThreadHandler().getLooper();
}
- /**
- * Set thread priority to audio.
- */
+ /** Set thread priority to audio. */
@CalledByNative
public static void setThreadPriorityAudio(int tid) {
Process.setThreadPriority(tid, Process.THREAD_PRIORITY_AUDIO);
diff --git a/base/android/java/src/org/chromium/base/TimeUtils.java b/base/android/java/src/org/chromium/base/TimeUtils.java
index b76a5f1..7e5f7af 100644
--- a/base/android/java/src/org/chromium/base/TimeUtils.java
+++ b/base/android/java/src/org/chromium/base/TimeUtils.java
@@ -67,8 +67,11 @@
interface FakeClock {
long uptimeMillis();
+
long elapsedRealtimeNanos();
+
long currentThreadTimeMillis();
+
long currentTimeMillis();
}
diff --git a/base/android/java/src/org/chromium/base/TimezoneUtils.java b/base/android/java/src/org/chromium/base/TimezoneUtils.java
index 3ea44b0..606b72e 100644
--- a/base/android/java/src/org/chromium/base/TimezoneUtils.java
+++ b/base/android/java/src/org/chromium/base/TimezoneUtils.java
@@ -13,10 +13,7 @@
@JNINamespace("base::android")
class TimezoneUtils {
- /**
- * Guards this class from being instantiated.
- */
-
+ /** Guards this class from being instantiated. */
private TimezoneUtils() {}
/**
diff --git a/base/android/java/src/org/chromium/base/TraceEvent.java b/base/android/java/src/org/chromium/base/TraceEvent.java
index d1f349a..2cea023 100644
--- a/base/android/java/src/org/chromium/base/TraceEvent.java
+++ b/base/android/java/src/org/chromium/base/TraceEvent.java
@@ -50,8 +50,10 @@
static class BasicLooperMonitor implements Printer {
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
static final String LOOPER_TASK_PREFIX = "Looper.dispatch: ";
+
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
static final String FILTERED_EVENT_NAME = LOOPER_TASK_PREFIX + "EVENT_NAME_FILTERED";
+
private static final int SHORTEST_LOG_PREFIX_LENGTH = "<<<<< Finished to ".length();
private String mCurrentTarget;
@@ -76,7 +78,7 @@
if (sEnabled) {
TraceEventJni.get().beginToplevel(mCurrentTarget);
} else {
- EarlyTraceEvent.begin(mCurrentTarget, true /*isToplevel*/);
+ EarlyTraceEvent.begin(mCurrentTarget, /* isToplevel= */ true);
}
}
}
@@ -87,7 +89,7 @@
if (sEnabled) {
TraceEventJni.get().endToplevel(mCurrentTarget);
} else {
- EarlyTraceEvent.end(mCurrentTarget, true /*isToplevel*/);
+ EarlyTraceEvent.end(mCurrentTarget, /* isToplevel= */ true);
}
}
mCurrentTarget = null;
@@ -160,8 +162,7 @@
// Calculation constants
private static final long FRAME_DURATION_MILLIS = 1000L / 60L; // 60 FPS
// A reasonable threshold for defining a Looper event as "long running"
- private static final long MIN_INTERESTING_DURATION_MILLIS =
- FRAME_DURATION_MILLIS;
+ private static final long MIN_INTERESTING_DURATION_MILLIS = FRAME_DURATION_MILLIS;
// A reasonable threshold for a "burst" of tasks on the Looper
private static final long MIN_INTERESTING_BURST_DURATION_MILLIS =
MIN_INTERESTING_DURATION_MILLIS * 3;
@@ -208,8 +209,7 @@
final void endHandling(final String line) {
final long elapsed = TimeUtils.elapsedRealtimeMillis() - mLastWorkStartedAt;
if (elapsed > MIN_INTERESTING_DURATION_MILLIS) {
- traceAndLog(Log.WARN, "observed a task that took "
- + elapsed + "ms: " + line);
+ traceAndLog(Log.WARN, "observed a task that took " + elapsed + "ms: " + line);
}
super.endHandling(line);
syncIdleMonitoring();
@@ -231,10 +231,15 @@
TraceEvent.begin(IDLE_EVENT_NAME, mNumTasksSinceLastIdle + " tasks since last idle.");
if (elapsed > MIN_INTERESTING_BURST_DURATION_MILLIS) {
// Dump stats
- String statsString = mNumTasksSeen + " tasks and "
- + mNumIdlesSeen + " idles processed so far, "
- + mNumTasksSinceLastIdle + " tasks bursted and "
- + elapsed + "ms elapsed since last idle";
+ String statsString =
+ mNumTasksSeen
+ + " tasks and "
+ + mNumIdlesSeen
+ + " idles processed so far, "
+ + mNumTasksSinceLastIdle
+ + " tasks bursted and "
+ + elapsed
+ + "ms elapsed since last idle";
traceAndLog(Log.DEBUG, statsString);
}
mLastIdleStartedAt = now;
@@ -247,22 +252,19 @@
private static final class LooperMonitorHolder {
private static final BasicLooperMonitor sInstance =
CommandLine.getInstance().hasSwitch(BaseSwitches.ENABLE_IDLE_TRACING)
- ? new IdleTracingLooperMonitor() : new BasicLooperMonitor();
+ ? new IdleTracingLooperMonitor()
+ : new BasicLooperMonitor();
}
private final String mName;
- /**
- * Constructor used to support the "try with resource" construct.
- */
+ /** Constructor used to support the "try with resource" construct. */
private TraceEvent(String name, String arg) {
mName = name;
begin(name, arg);
}
- /**
- * Constructor used to support the "try with resource" construct.
- */
+ /** Constructor used to support the "try with resource" construct. */
private TraceEvent(String name, int arg) {
mName = name;
begin(name, arg);
@@ -301,16 +303,12 @@
return new TraceEvent(name, arg);
}
- /**
- * Similar to {@link #scoped(String, String arg)}, but uses null for |arg|.
- */
+ /** Similar to {@link #scoped(String, String arg)}, but uses null for |arg|. */
public static TraceEvent scoped(String name) {
return scoped(name, null);
}
- /**
- * Notification from native that tracing is enabled/disabled.
- */
+ /** Notification from native that tracing is enabled/disabled. */
@CalledByNative
public static void setEnabled(boolean enabled) {
if (enabled) EarlyTraceEvent.disable();
@@ -318,8 +316,8 @@
// by other applications
if (sEnabled != enabled) {
sEnabled = enabled;
- ThreadUtils.getUiThreadLooper().setMessageLogging(
- enabled ? LooperMonitorHolder.sInstance : null);
+ ThreadUtils.getUiThreadLooper()
+ .setMessageLogging(enabled ? LooperMonitorHolder.sInstance : null);
}
if (sUiThreadReady) {
ViewHierarchyDumper.updateEnabledState();
@@ -482,10 +480,12 @@
// quite slow.
long flow = views.hashCode();
- PostTask.postTask(TaskTraits.BEST_EFFORT, () -> {
- // Actually output the dump as a trace event on a thread pool.
- TraceEventJni.get().initViewHierarchyDump(flow, views);
- });
+ PostTask.postTask(
+ TaskTraits.BEST_EFFORT,
+ () -> {
+ // Actually output the dump as a trace event on a thread pool.
+ TraceEventJni.get().initViewHierarchyDump(flow, views);
+ });
TraceEvent.end("instantAndroidViewHierarchy", null, flow);
}
}
@@ -528,7 +528,7 @@
* @param arg The arguments of the event.
*/
public static void begin(String name, String arg) {
- EarlyTraceEvent.begin(name, false /*isToplevel*/);
+ EarlyTraceEvent.begin(name, /* isToplevel= */ false);
if (sEnabled) {
TraceEventJni.get().begin(name, arg);
}
@@ -540,7 +540,7 @@
* @param arg An integer argument of the event.
*/
public static void begin(String name, int arg) {
- EarlyTraceEvent.begin(name, false /*isToplevel*/);
+ EarlyTraceEvent.begin(name, /* isToplevel= */ false);
if (sEnabled) {
TraceEventJni.get().beginWithIntArg(name, arg);
}
@@ -570,7 +570,7 @@
* @param flow The flow ID to associate with this event (0 is treated as invalid).
*/
public static void end(String name, String arg, long flow) {
- EarlyTraceEvent.end(name, false /*isToplevel*/);
+ EarlyTraceEvent.end(name, /* isToplevel= */ false);
if (sEnabled) {
TraceEventJni.get().end(name, arg, flow);
}
@@ -585,8 +585,10 @@
ArrayList<ActivityInfo> views = new ArrayList<>(2);
for (Activity a : ApplicationStatus.getRunningActivities()) {
views.add(new ActivityInfo(a.getClass().getName()));
- ViewHierarchyDumper.dumpView(views.get(views.size() - 1),
- /*parentId=*/0, a.getWindow().getDecorView().getRootView());
+ ViewHierarchyDumper.dumpView(
+ views.get(views.size() - 1),
+ /* parentId= */ 0,
+ a.getWindow().getDecorView().getRootView());
}
return views;
}
@@ -594,25 +596,50 @@
@NativeMethods
interface Natives {
void registerEnabledObserver();
+
void instant(String name, String arg);
+
void begin(String name, String arg);
+
void beginWithIntArg(String name, int arg);
+
void end(String name, String arg, long flow);
+
void beginToplevel(String target);
+
void endToplevel(String target);
+
void startAsync(String name, long id);
+
void finishAsync(String name, long id);
+
boolean viewHierarchyDumpEnabled();
+
void initViewHierarchyDump(long id, Object list);
+
long startActivityDump(String name, long dumpProtoPtr);
- void addViewDump(int id, int parentId, boolean isShown, boolean isDirty, String className,
- String resourceName, long activityProtoPtr);
+
+ void addViewDump(
+ int id,
+ int parentId,
+ boolean isShown,
+ boolean isDirty,
+ String className,
+ String resourceName,
+ long activityProtoPtr);
+
void instantAndroidIPC(String name, long durMs);
+
void instantAndroidToolbar(int blockReason, int allowReason, int snapshotDiff);
+
void webViewStartupTotalFactoryInit(long startTimeMs, long durationMs);
+
void webViewStartupStage1(long startTimeMs, long durationMs);
+
void webViewStartupStage2(long startTimeMs, long durationMs, boolean isColdStartup);
+
void startupLaunchCause(long activityId, int launchCause);
+
void startupTimeToFirstVisibleContent2(long activityId, long startTimeMs, long durationMs);
}
@@ -638,15 +665,24 @@
// java exceptions aren't he fastest thing ever.
String resource;
try {
- resource = view.mRes != null ? (view.mId == 0 || view.mId == -1
- ? "__no_id__"
- : view.mRes.getResourceName(view.mId))
- : "__no_resources__";
+ resource =
+ view.mRes != null
+ ? (view.mId == 0 || view.mId == -1
+ ? "__no_id__"
+ : view.mRes.getResourceName(view.mId))
+ : "__no_resources__";
} catch (NotFoundException e) {
resource = "__name_not_found__";
}
- TraceEventJni.get().addViewDump(view.mId, view.mParentId, view.mIsShown,
- view.mIsDirty, view.mClassName, resource, activityProtoPtr);
+ TraceEventJni.get()
+ .addViewDump(
+ view.mId,
+ view.mParentId,
+ view.mIsShown,
+ view.mIsDirty,
+ view.mClassName,
+ resource,
+ activityProtoPtr);
}
}
}
@@ -657,7 +693,12 @@
* event off the main thread.
*/
public static class ViewInfo {
- public ViewInfo(int id, int parentId, boolean isShown, boolean isDirty, String className,
+ public ViewInfo(
+ int id,
+ int parentId,
+ boolean isShown,
+ boolean isDirty,
+ String className,
android.content.res.Resources res) {
mId = id;
mParentId = parentId;
@@ -730,25 +771,33 @@
}
public static void updateEnabledState() {
- PostTask.runOrPostTask(TaskTraits.UI_DEFAULT, () -> {
- if (TraceEventJni.get().viewHierarchyDumpEnabled()) {
- if (sInstance == null) {
- sInstance = new ViewHierarchyDumper();
- }
- enable();
- } else {
- if (sInstance != null) {
- disable();
- }
- }
- });
+ PostTask.runOrPostTask(
+ TaskTraits.UI_DEFAULT,
+ () -> {
+ if (TraceEventJni.get().viewHierarchyDumpEnabled()) {
+ if (sInstance == null) {
+ sInstance = new ViewHierarchyDumper();
+ }
+ enable();
+ } else {
+ if (sInstance != null) {
+ disable();
+ }
+ }
+ });
}
private static void dumpView(ActivityInfo collection, int parentId, View v) {
ThreadUtils.assertOnUiThread();
int id = v.getId();
- collection.mViews.add(new ViewInfo(id, parentId, v.isShown(), v.isDirty(),
- v.getClass().getSimpleName(), v.getResources()));
+ collection.mViews.add(
+ new ViewInfo(
+ id,
+ parentId,
+ v.isShown(),
+ v.isDirty(),
+ v.getClass().getSimpleName(),
+ v.getResources()));
if (v instanceof ViewGroup) {
ViewGroup vg = (ViewGroup) v;
diff --git a/base/android/java/src/org/chromium/base/UnguessableToken.java b/base/android/java/src/org/chromium/base/UnguessableToken.java
index e93fb85..08a49d1 100644
--- a/base/android/java/src/org/chromium/base/UnguessableToken.java
+++ b/base/android/java/src/org/chromium/base/UnguessableToken.java
@@ -104,4 +104,5 @@
return token;
}
-};
+}
+;
diff --git a/base/android/java/src/org/chromium/base/UnownedUserDataHost.java b/base/android/java/src/org/chromium/base/UnownedUserDataHost.java
index 40fdef5..ec14532 100644
--- a/base/android/java/src/org/chromium/base/UnownedUserDataHost.java
+++ b/base/android/java/src/org/chromium/base/UnownedUserDataHost.java
@@ -157,9 +157,7 @@
*/
private Handler mHandler;
- /**
- * The core data structure within this host.
- */
+ /** The core data structure within this host. */
private HashMap<UnownedUserDataKey<?>, WeakReference<? extends UnownedUserData>>
mUnownedUserDataMap = new HashMap<>();
@@ -174,14 +172,14 @@
/**
* Stores a {@link WeakReference} to {@code object} using the given {@code key}.
- * <p>
- * If the key is already attached to a different host, it is detached from that host.
*
- * @param key the key to use for the object.
+ * <p>If the key is already attached to a different host, it is detached from that host.
+ *
+ * @param key the key to use for the object.
* @param newValue the object to store.
- * @param <T> the type of {@link UnownedUserData}.
+ * @param <T> the type of {@link UnownedUserData}.
*/
- /* package */<T extends UnownedUserData> void set(
+ /* package */ <T extends UnownedUserData> void set(
@NonNull UnownedUserDataKey<T> key, @NonNull T newValue) {
checkState();
@@ -203,7 +201,7 @@
* @return the stored version or {@code null} if it is not stored or has been garbage collected.
*/
@Nullable
- /* package */<T extends UnownedUserData> T get(@NonNull UnownedUserDataKey<T> key) {
+ /* package */ <T extends UnownedUserData> T get(@NonNull UnownedUserDataKey<T> key) {
checkState();
WeakReference<? extends UnownedUserData> valueWeakRef = mUnownedUserDataMap.get(key);
@@ -223,7 +221,7 @@
* @param key the key to use for the object.
* @param <T> the type of {@link UnownedUserData}.
*/
- /* package */<T extends UnownedUserData> void remove(@NonNull UnownedUserDataKey<T> key) {
+ /* package */ <T extends UnownedUserData> void remove(@NonNull UnownedUserDataKey<T> key) {
checkState();
WeakReference<? extends UnownedUserData> valueWeakRef = mUnownedUserDataMap.remove(key);
diff --git a/base/android/java/src/org/chromium/base/UnownedUserDataKey.java b/base/android/java/src/org/chromium/base/UnownedUserDataKey.java
index cc61f3d7..9a6b5b6 100644
--- a/base/android/java/src/org/chromium/base/UnownedUserDataKey.java
+++ b/base/android/java/src/org/chromium/base/UnownedUserDataKey.java
@@ -62,8 +62,7 @@
* @see UnownedUserData for the marker interface used for this type of data.
*/
public final class UnownedUserDataKey<T extends UnownedUserData> {
- @NonNull
- private final Class<T> mClazz;
+ @NonNull private final Class<T> mClazz;
// A Set that uses WeakReference<UnownedUserDataHost> internally.
private final Set<UnownedUserDataHost> mWeakHostAttachments =
Collections.newSetFromMap(new WeakHashMap<>());
diff --git a/base/android/java/src/org/chromium/base/UserData.java b/base/android/java/src/org/chromium/base/UserData.java
index 968d29a..53d8f29 100644
--- a/base/android/java/src/org/chromium/base/UserData.java
+++ b/base/android/java/src/org/chromium/base/UserData.java
@@ -11,10 +11,12 @@
public interface UserData {
/**
* Called when {@link UserData} object needs to be destroyed.
+ *
+ * <pre>
* WARNING: This method is not guaranteed to be called. Each host class should
* call {@link UserDataHost#destroy()} explicitly at the end of its
* lifetime to have all of its {@link UserData#destroy()} get invoked.
+ * </pre>
*/
- default void
- destroy() {}
+ default void destroy() {}
}
diff --git a/base/android/java/src/org/chromium/base/UserDataHost.java b/base/android/java/src/org/chromium/base/UserDataHost.java
index de2bd37..bad122e 100644
--- a/base/android/java/src/org/chromium/base/UserDataHost.java
+++ b/base/android/java/src/org/chromium/base/UserDataHost.java
@@ -9,22 +9,18 @@
import java.util.HashMap;
/**
- * A class that implements type-safe heterogeneous container. It can associate
- * an object of type T with a type token (T.class) as a key. Mismatch of the
- * type between them can be checked at compile time, hence type-safe. Objects
- * are held using strong reference in the container. {@code null} is not allowed
- * for key or object.
- * <p>
- * Can be used for an object that needs to have other objects attached to it
- * without having to manage explicit references to them. Attached objects need
- * to implement {@link UserData} so that they can be destroyed by {@link #destroy()}.
- * <p>
- * No operation takes effect once {@link #destroy()} is called.
- * <p>
- * Usage:
-
+ * A class that implements type-safe heterogeneous container. It can associate an object of type T
+ * with a type token (T.class) as a key. Mismatch of the type between them can be checked at compile
+ * time, hence type-safe. Objects are held using strong reference in the container. {@code null} is
+ * not allowed for key or object.
*
- * <code>
+ * <p>Can be used for an object that needs to have other objects attached to it without having to
+ * manage explicit references to them. Attached objects need to implement {@link UserData} so that
+ * they can be destroyed by {@link #destroy()}.
+ *
+ * <p>No operation takes effect once {@link #destroy()} is called.
+ *
+ * <p>Usage: <code>
* public class Foo {
* // Defines the container.
* private final UserDataHost mUserDataHost = new UserDataHost();
diff --git a/base/android/java/src/org/chromium/base/compat/ApiHelperForM.java b/base/android/java/src/org/chromium/base/compat/ApiHelperForM.java
index fc1fdc8..202d650 100644
--- a/base/android/java/src/org/chromium/base/compat/ApiHelperForM.java
+++ b/base/android/java/src/org/chromium/base/compat/ApiHelperForM.java
@@ -35,17 +35,13 @@
public final class ApiHelperForM {
private ApiHelperForM() {}
- /**
- * See {@link WebViewClient#onPageCommitVisible(WebView, String)}, which was added in M.
- */
+ /** See {@link WebViewClient#onPageCommitVisible(WebView, String)}, which was added in M. */
public static void onPageCommitVisible(
WebViewClient webViewClient, WebView webView, String url) {
webViewClient.onPageCommitVisible(webView, url);
}
- /**
- * See {@link Process#is64Bit()}.
- */
+ /** See {@link Process#is64Bit()}. */
public static boolean isProcess64Bit() {
return Process.is64Bit();
}
@@ -85,8 +81,8 @@
/** See {@link PackageManager#isPermissionRevokedByPolicy(String, String)}. */
public static boolean isPermissionRevokedByPolicy(Activity activity, String permission) {
- return activity.getPackageManager().isPermissionRevokedByPolicy(
- permission, activity.getPackageName());
+ return activity.getPackageManager()
+ .isPermissionRevokedByPolicy(permission, activity.getPackageName());
}
/** See {@link NetworkSecurityPolicy#isCleartextTrafficPermitted()}. */
diff --git a/base/android/java/src/org/chromium/base/compat/ApiHelperForN.java b/base/android/java/src/org/chromium/base/compat/ApiHelperForN.java
index 221960e..ffd662e 100644
--- a/base/android/java/src/org/chromium/base/compat/ApiHelperForN.java
+++ b/base/android/java/src/org/chromium/base/compat/ApiHelperForN.java
@@ -30,8 +30,12 @@
private ApiHelperForN() {}
/** See {@link View#startDragAndDrop(ClipData, DragShadowBuilder, Object, int)}. */
- public static boolean startDragAndDrop(View view, ClipData data,
- DragShadowBuilder shadowBuilder, Object myLocalState, int flags) {
+ public static boolean startDragAndDrop(
+ View view,
+ ClipData data,
+ DragShadowBuilder shadowBuilder,
+ Object myLocalState,
+ int flags) {
return view.startDragAndDrop(data, shadowBuilder, myLocalState, flags);
}
@@ -41,8 +45,9 @@
}
/** See {@link Activity#setVrModeEnabled(boolean, ComponentName)}. */
- public static void setVrModeEnabled(Activity activity, boolean enabled,
- ComponentName requestedComponent) throws PackageManager.NameNotFoundException {
+ public static void setVrModeEnabled(
+ Activity activity, boolean enabled, ComponentName requestedComponent)
+ throws PackageManager.NameNotFoundException {
activity.setVrModeEnabled(enabled, requestedComponent);
}
diff --git a/base/android/java/src/org/chromium/base/compat/ApiHelperForO.java b/base/android/java/src/org/chromium/base/compat/ApiHelperForO.java
index cb61985..e403ef4 100644
--- a/base/android/java/src/org/chromium/base/compat/ApiHelperForO.java
+++ b/base/android/java/src/org/chromium/base/compat/ApiHelperForO.java
@@ -121,8 +121,10 @@
* ConnectivityManager#registerDefaultNetworkCallback(ConnectivityManager.NetworkCallback,
* Handler) }.
*/
- public static void registerDefaultNetworkCallback(ConnectivityManager connectivityManager,
- NetworkCallback networkCallback, Handler handler) {
+ public static void registerDefaultNetworkCallback(
+ ConnectivityManager connectivityManager,
+ NetworkCallback networkCallback,
+ Handler handler) {
connectivityManager.registerDefaultNetworkCallback(networkCallback, handler);
}
@@ -134,14 +136,17 @@
/**
* See {@link Context#registerReceiver(BroadcastReceiver, IntentFilter, String, Handler, int)}
*/
- public static Intent registerReceiver(Context context, BroadcastReceiver receiver,
- IntentFilter filter, String permission, Handler scheduler, int flags) {
+ public static Intent registerReceiver(
+ Context context,
+ BroadcastReceiver receiver,
+ IntentFilter filter,
+ String permission,
+ Handler scheduler,
+ int flags) {
return context.registerReceiver(receiver, filter, permission, scheduler, flags);
}
- /**
- * See {@link ClipData#addItem(ContentResolver, Item)}.
- */
+ /** See {@link ClipData#addItem(ContentResolver, Item)}. */
public static void addItem(ClipData clipData, ContentResolver contentResolver, Item item) {
clipData.addItem(contentResolver, item);
}
diff --git a/base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java b/base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java
index 4fd4862..f8272ce 100644
--- a/base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java
+++ b/base/android/java/src/org/chromium/base/compat/ApiHelperForQ.java
@@ -49,7 +49,8 @@
public static void requestCellInfoUpdate(
TelephonyManager telephonyManager, Callback<List<CellInfo>> callback) {
telephonyManager.requestCellInfoUpdate(
- AsyncTask.THREAD_POOL_EXECUTOR, new TelephonyManager.CellInfoCallback() {
+ AsyncTask.THREAD_POOL_EXECUTOR,
+ new TelephonyManager.CellInfoCallback() {
@Override
@SuppressLint("Override")
public void onCellInfo(List<CellInfo> cellInfos) {
@@ -58,8 +59,13 @@
});
}
- public static boolean bindIsolatedService(Context context, Intent intent, int flags,
- String instanceName, Executor executor, ServiceConnection connection) {
+ public static boolean bindIsolatedService(
+ Context context,
+ Intent intent,
+ int flags,
+ String instanceName,
+ Executor executor,
+ ServiceConnection connection) {
return context.bindIsolatedService(intent, flags, instanceName, executor, connection);
}
diff --git a/base/android/java/src/org/chromium/base/compat/ApiHelperForR.java b/base/android/java/src/org/chromium/base/compat/ApiHelperForR.java
index c8ebcaa..5db282c 100644
--- a/base/android/java/src/org/chromium/base/compat/ApiHelperForR.java
+++ b/base/android/java/src/org/chromium/base/compat/ApiHelperForR.java
@@ -41,16 +41,12 @@
return manager.getStorageVolume(uri).getDirectory();
}
- /**
- * See {@link InputManager#verifyInputEvent(InputEvent)}.
- */
+ /** See {@link InputManager#verifyInputEvent(InputEvent)}. */
public static VerifiedInputEvent verifyInputEvent(InputManager manager, InputEvent inputEvent) {
return manager.verifyInputEvent(inputEvent);
}
- /**
- * See {@link android.app.ActivityManager#setProcessStateSummary(byte[])}
- */
+ /** See {@link android.app.ActivityManager#setProcessStateSummary(byte[])} */
public static void setProcessStateSummary(ActivityManager am, byte[] bytes) {
am.setProcessStateSummary(bytes);
}
diff --git a/base/android/java/src/org/chromium/base/compat/ApiHelperForS.java b/base/android/java/src/org/chromium/base/compat/ApiHelperForS.java
index 0d24313..c5b1bc1 100644
--- a/base/android/java/src/org/chromium/base/compat/ApiHelperForS.java
+++ b/base/android/java/src/org/chromium/base/compat/ApiHelperForS.java
@@ -40,16 +40,12 @@
private ApiHelperForS() {}
- /**
- * See {@link ClipDescription#isStyleText()}.
- */
+ /** See {@link ClipDescription#isStyleText()}. */
public static boolean isStyleText(ClipDescription clipDescription) {
return clipDescription.isStyledText();
}
- /**
- * See {@link ClipDescription#getConfidenceScore()}.
- */
+ /** See {@link ClipDescription#getConfidenceScore()}. */
public static float getConfidenceScore(
ClipDescription clipDescription, @NonNull String entityType) {
return clipDescription.getConfidenceScore(entityType);
@@ -63,22 +59,21 @@
return clipDescription.getClassificationStatus() == ClipDescription.CLASSIFICATION_COMPLETE;
}
- /**
- * See {@link ClipData.Item#getTextLinks()}.
- */
+ /** See {@link ClipData.Item#getTextLinks()}. */
public static TextLinks getTextLinks(ClipData.Item item) {
return item.getTextLinks();
}
public static boolean hasBluetoothConnectPermission() {
- return ApiCompatibilityUtils.checkPermission(ContextUtils.getApplicationContext(),
- Manifest.permission.BLUETOOTH_CONNECT, Process.myPid(), Process.myUid())
+ return ApiCompatibilityUtils.checkPermission(
+ ContextUtils.getApplicationContext(),
+ Manifest.permission.BLUETOOTH_CONNECT,
+ Process.myPid(),
+ Process.myUid())
== PackageManager.PERMISSION_GRANTED;
}
- /**
- * See {@link android.app.PictureInPictureParams.Builder#setAutoEnterEnabled(boolean)}
- */
+ /** See {@link android.app.PictureInPictureParams.Builder#setAutoEnterEnabled(boolean)} */
public static void setAutoEnterEnabled(
PictureInPictureParams.Builder builder, boolean enabled) {
builder.setAutoEnterEnabled(enabled);
@@ -93,24 +88,18 @@
return builder.setIncludeTextClassification(includeTextClassification);
}
- /**
- * See {@link android.view.textclassifier.TextSelection#getTextClassification()}
- */
+ /** See {@link android.view.textclassifier.TextSelection#getTextClassification()} */
public static TextClassification getTextClassification(TextSelection textSelection) {
return textSelection.getTextClassification();
}
- /**
- * See Context#createWindowContext.
- */
+ /** See Context#createWindowContext. */
public static Context createWindowContext(
Context context, Display display, int type, Bundle options) {
return context.createWindowContext(display, type, options);
}
- /**
- * See {@link PendingIntent#FLAG_MUTABLE}.
- */
+ /** See {@link PendingIntent#FLAG_MUTABLE}. */
public static int getPendingIntentMutableFlag() {
return PendingIntent.FLAG_MUTABLE;
}
@@ -121,9 +110,14 @@
try {
service.startForeground(id, notification, foregroundServiceType);
} catch (ForegroundServiceStartNotAllowedException e) {
- Log.e(TAG,
- "Cannot run service as foreground: " + e + " for notification channel "
- + notification.getChannelId() + " notification id " + id);
+ Log.e(
+ TAG,
+ "Cannot run service as foreground: "
+ + e
+ + " for notification channel "
+ + notification.getChannelId()
+ + " notification id "
+ + id);
}
}
}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java
index 673afb3..279ac61 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsListener.java
@@ -95,8 +95,8 @@
long frameTotalDurationNs = frameMetrics.getMetric(FrameMetrics.TOTAL_DURATION);
long frame_start_vsync_ts = frameMetrics.getMetric(FrameMetrics.VSYNC_TIMESTAMP);
- try (TraceEvent e = TraceEvent.scoped(
- "onFrameMetricsAvailable", Long.toString(frameTotalDurationNs))) {
+ try (TraceEvent e =
+ TraceEvent.scoped("onFrameMetricsAvailable", Long.toString(frameTotalDurationNs))) {
// FrameMetrics.DEADLINE was added in API level 31(S).
// TODO(b/311139161): Update RequiresApi level to Android S.
long deadlineNs = frameMetrics.getMetric(FrameMetrics.DEADLINE);
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java
index ccdfcc9..c300b64 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/FrameMetricsStore.java
@@ -4,7 +4,6 @@
package org.chromium.base.jank_tracker;
-
import org.chromium.base.ThreadUtils.ThreadChecker;
import org.chromium.base.TimeUtils;
import org.chromium.base.TraceEvent;
@@ -104,7 +103,7 @@
@SuppressWarnings("NoDynamicStringsInTraceEventCheck")
void startTrackingScenario(@JankScenario int scenario) {
try (TraceEvent e =
- TraceEvent.scoped("startTrackingScenario: " + scenarioToString(scenario))) {
+ TraceEvent.scoped("startTrackingScenario: " + scenarioToString(scenario))) {
mThreadChecker.assertOnValidThread();
// Ignore multiple calls to startTrackingScenario without corresponding
// stopTrackingScenario calls.
@@ -136,8 +135,9 @@
@SuppressWarnings("NoDynamicStringsInTraceEventCheck")
JankMetrics stopTrackingScenario(@JankScenario int scenario, long endScenarioTimeNs) {
try (TraceEvent e =
- TraceEvent.scoped("finishTrackingScenario: " + scenarioToString(scenario),
- Long.toString(endScenarioTimeNs))) {
+ TraceEvent.scoped(
+ "finishTrackingScenario: " + scenarioToString(scenario),
+ Long.toString(endScenarioTimeNs))) {
mThreadChecker.assertOnValidThread();
TraceEvent.finishAsync(
"JankCUJ:" + scenarioToString(scenario), TRACE_EVENT_TRACK_ID + scenario);
@@ -166,8 +166,8 @@
// Ending index is exclusive, so this is not out of bounds.
int endingIndex = mTimestampsNs.size();
if (endScenarioTimeNs > 0) {
- // binarySearch returns
- // index of the search key (non-negative value) or (-(insertion point) - 1).
+ // binarySearch returns index of the search key (non-negative value) or (-(insertion
+ // point) - 1).
// The insertion point is defined as the index of the first element greater than the
// key, or a.length if all elements in the array are less than the specified key.
endingIndex = Collections.binarySearch(mTimestampsNs, endScenarioTimeNs);
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
index b664fc1..25286eb 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankActivityTracker.java
@@ -29,7 +29,9 @@
private WeakReference<Activity> mActivityReference;
- JankActivityTracker(Activity context, FrameMetricsListener listener,
+ JankActivityTracker(
+ Activity context,
+ FrameMetricsListener listener,
JankReportingScheduler reportingScheduler) {
super(listener, reportingScheduler);
mActivityReference = new WeakReference<>(context);
@@ -41,8 +43,7 @@
Activity activity = mActivityReference.get();
if (activity != null) {
ApplicationStatus.registerStateListenerForActivity(this, activity);
- @ActivityState
- int activityState = ApplicationStatus.getStateForActivity(activity);
+ @ActivityState int activityState = ApplicationStatus.getStateForActivity(activity);
onActivityStateChange(activity, activityState);
startMetricCollection(activity.getWindow());
}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java b/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java
index d5a5ce8..e634d75 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankMetricUMARecorder.java
@@ -7,13 +7,14 @@
import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
-/**
- * Sends Android jank metrics to native to be recorded using UMA.
- */
+/** Sends Android jank metrics to native to be recorded using UMA. */
@JNINamespace("base::android")
public class JankMetricUMARecorder {
- public static void recordJankMetricsToUMA(JankMetrics metric, long reportingIntervalStartTime,
- long reportingIntervalDuration, @JankScenario int scenario) {
+ public static void recordJankMetricsToUMA(
+ JankMetrics metric,
+ long reportingIntervalStartTime,
+ long reportingIntervalDuration,
+ @JankScenario int scenario) {
if (metric == null) {
return;
}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java
index 272b56d..2028081 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingRunnable.java
@@ -7,6 +7,7 @@
import android.os.Handler;
import org.chromium.base.TraceEvent;
+
/**
* This runnable receives a FrameMetricsStore instance and starts/stops tracking a given scenario.
* When a scenario stops it takes its metrics and sends them to native to be recorded in UMA.
@@ -34,8 +35,9 @@
metrics = mMetricsStore.stopTrackingScenario(mScenario);
} else {
// Since this is after the timeout we just unconditionally get the metrics.
- metrics = mMetricsStore.stopTrackingScenario(
- mScenario, mJankEndScenarioTime.endScenarioTimeNs);
+ metrics =
+ mMetricsStore.stopTrackingScenario(
+ mScenario, mJankEndScenarioTime.endScenarioTimeNs);
}
if (metrics == null || metrics.timestampsNs.length == 0) {
@@ -60,8 +62,12 @@
}
}
- JankReportingRunnable(FrameMetricsStore metricsStore, @JankScenario int scenario,
- boolean isStartingTracking, Handler handler, JankEndScenarioTime endScenarioTime) {
+ JankReportingRunnable(
+ FrameMetricsStore metricsStore,
+ @JankScenario int scenario,
+ boolean isStartingTracking,
+ Handler handler,
+ JankEndScenarioTime endScenarioTime) {
mMetricsStore = metricsStore;
mScenario = scenario;
mIsStartingTracking = isStartingTracking;
@@ -71,9 +77,13 @@
@Override
public void run() {
- try (TraceEvent e = TraceEvent.scoped("StartingOrStoppingJankScenario",
- "StartingScenario:" + Boolean.toString(mIsStartingTracking)
- + ",Scenario:" + Integer.toString(mScenario))) {
+ try (TraceEvent e =
+ TraceEvent.scoped(
+ "StartingOrStoppingJankScenario",
+ "StartingScenario:"
+ + Boolean.toString(mIsStartingTracking)
+ + ",Scenario:"
+ + Integer.toString(mScenario))) {
if (mIsStartingTracking) {
if (mMetricsStore == null) {
TraceEvent.instant("StartTrackingScenario metrics store null");
@@ -82,10 +92,11 @@
mMetricsStore.startTrackingScenario(mScenario);
return;
}
- boolean dataIsReady = mJankEndScenarioTime == null
- || (mJankEndScenarioTime != null
- && mMetricsStore.hasReceivedMetricsPast(
- mJankEndScenarioTime.endScenarioTimeNs));
+ boolean dataIsReady =
+ mJankEndScenarioTime == null
+ || (mJankEndScenarioTime != null
+ && mMetricsStore.hasReceivedMetricsPast(
+ mJankEndScenarioTime.endScenarioTimeNs));
if (dataIsReady) {
new FinalReportingRunnable().run();
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java
index ac15874..a19caac 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankReportingScheduler.java
@@ -28,25 +28,26 @@
mRunnableStore = new HashMap<Integer, JankReportingRunnable>();
}
- private final Runnable mPeriodicMetricReporter = new Runnable() {
- @Override
- public void run() {
- // delay should never be null.
- finishTrackingScenario(JankScenario.PERIODIC_REPORTING);
+ private final Runnable mPeriodicMetricReporter =
+ new Runnable() {
+ @Override
+ public void run() {
+ // delay should never be null.
+ finishTrackingScenario(JankScenario.PERIODIC_REPORTING);
- if (mIsPeriodicReporterLooping.get()) {
- // We delay starting the next periodic reporting until the timeout has finished by
- // taking the delay and +1 so that it will run in order (it was posted above).
- startTrackingScenario(JankScenario.PERIODIC_REPORTING);
- getOrCreateHandler().postDelayed(mPeriodicMetricReporter, PERIODIC_METRIC_DELAY_MS);
- }
- }
- };
+ if (mIsPeriodicReporterLooping.get()) {
+ // We delay starting the next periodic reporting until the timeout has
+ // finished by taking the delay and +1 so that it will run in order (it
+ // was posted above).
+ startTrackingScenario(JankScenario.PERIODIC_REPORTING);
+ getOrCreateHandler()
+ .postDelayed(mPeriodicMetricReporter, PERIODIC_METRIC_DELAY_MS);
+ }
+ }
+ };
- @Nullable
- protected HandlerThread mHandlerThread;
- @Nullable
- private Handler mHandler;
+ @Nullable protected HandlerThread mHandlerThread;
+ @Nullable private Handler mHandler;
private final AtomicBoolean mIsPeriodicReporterLooping = new AtomicBoolean(false);
public void startTrackingScenario(@JankScenario int scenario) {
@@ -59,8 +60,14 @@
getOrCreateHandler().removeCallbacks(stopTask);
mRunnableStore.remove(scenario);
}
- getOrCreateHandler().post(new JankReportingRunnable(
- mFrameMetricsStore, scenario, /* isStartingTracking= */ true, mHandler, null));
+ getOrCreateHandler()
+ .post(
+ new JankReportingRunnable(
+ mFrameMetricsStore,
+ scenario,
+ /* isStartingTracking= */ true,
+ mHandler,
+ null));
}
public void finishTrackingScenario(@JankScenario int scenario) {
@@ -75,9 +82,15 @@
@JankScenario int scenario, JankEndScenarioTime endScenarioTime) {
// We store the stop task in case the delay is greater than zero and we start this scenario
// again.
- JankReportingRunnable runnable = mRunnableStore.getOrDefault(scenario,
- new JankReportingRunnable(mFrameMetricsStore, scenario,
- /* isStartingTracking= */ false, mHandler, endScenarioTime));
+ JankReportingRunnable runnable =
+ mRunnableStore.getOrDefault(
+ scenario,
+ new JankReportingRunnable(
+ mFrameMetricsStore,
+ scenario,
+ /* isStartingTracking= */ false,
+ mHandler,
+ endScenarioTime));
getOrCreateHandler().post(runnable);
}
@@ -86,12 +99,13 @@
mHandlerThread = new HandlerThread("Jank-Tracker");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mFrameMetricsStore.initialize();
- }
- });
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ mFrameMetricsStore.initialize();
+ }
+ });
}
return mHandler;
}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java b/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java
index ef789ce..9a59b5c 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankScenario.java
@@ -13,14 +13,22 @@
* A list of jank scenarios to be tracked, each scenario corresponds to a specific user journey
* except by PERIODIC_REPORTING, which runs constantly and is uploaded every 30s.
*
- * IMPORTANT: This must be kept up to date with the histograms.xml histograms
+ * <p>IMPORTANT: This must be kept up to date with the histograms.xml histograms
* (Android.FrameTimelineJank..*) and the JankScenario C++ enum in
* //base/android/jank_metric_uma_recorder.cc.
*/
-@IntDef({JankScenario.PERIODIC_REPORTING, JankScenario.OMNIBOX_FOCUS, JankScenario.NEW_TAB_PAGE,
- JankScenario.STARTUP, JankScenario.TAB_SWITCHER, JankScenario.OPEN_LINK_IN_NEW_TAB,
- JankScenario.START_SURFACE_HOMEPAGE, JankScenario.START_SURFACE_TAB_SWITCHER,
- JankScenario.FEED_SCROLLING, JankScenario.WEBVIEW_SCROLLING})
+@IntDef({
+ JankScenario.PERIODIC_REPORTING,
+ JankScenario.OMNIBOX_FOCUS,
+ JankScenario.NEW_TAB_PAGE,
+ JankScenario.STARTUP,
+ JankScenario.TAB_SWITCHER,
+ JankScenario.OPEN_LINK_IN_NEW_TAB,
+ JankScenario.START_SURFACE_HOMEPAGE,
+ JankScenario.START_SURFACE_TAB_SWITCHER,
+ JankScenario.FEED_SCROLLING,
+ JankScenario.WEBVIEW_SCROLLING
+})
@Retention(RetentionPolicy.SOURCE)
public @interface JankScenario {
int PERIODIC_REPORTING = 1;
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java
index 80ea847..77efb80 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTracker.java
@@ -4,9 +4,7 @@
package org.chromium.base.jank_tracker;
-/**
- * Interface for Android UI jank tracking.
- */
+/** Interface for Android UI jank tracking. */
public interface JankTracker {
/**
* Starts tracking UI jank for a specific use scenario (e.g. Tab switcher, Omnibox, etc.),
@@ -26,10 +24,9 @@
* that should be included.
*/
void finishTrackingScenario(@JankScenario int scenario, long endScenarioTimeNs);
+
void finishTrackingScenario(@JankScenario int scenario);
- /**
- * To be called when the jank tracker should stop listening to changes.
- */
+ /** To be called when the jank tracker should stop listening to changes. */
void destroy();
}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java
index 59f8518..b18a918 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerImpl.java
@@ -30,8 +30,9 @@
FrameMetricsStore metricsStore = new FrameMetricsStore();
if (!constructInternalPreController(new JankReportingScheduler(metricsStore))) return;
- constructInternalFinal(new JankActivityTracker(
- activity, new FrameMetricsListener(metricsStore), mReportingScheduler));
+ constructInternalFinal(
+ new JankActivityTracker(
+ activity, new FrameMetricsListener(metricsStore), mReportingScheduler));
}
/**
@@ -77,9 +78,7 @@
mReportingScheduler.finishTrackingScenario(scenario, endScenarioTimeNs);
}
- /**
- * Stops listening for Activity state changes.
- */
+ /** Stops listening for Activity state changes. */
@Override
public void destroy() {
if (!IS_TRACKING_ENABLED) return;
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java
index b73883d..2de3d2c 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/JankTrackerStateController.java
@@ -48,7 +48,10 @@
window.removeOnFrameMetricsAvailableListener(mFrameMetricsListener);
} catch (IllegalArgumentException e) {
// Adding the listener failed for whatever reason, so it could not be unregistered.
- Log.e(TAG, "Could not remove listener %s from window %s", mFrameMetricsListener,
+ Log.e(
+ TAG,
+ "Could not remove listener %s from window %s",
+ mFrameMetricsListener,
window);
}
}
@@ -56,5 +59,6 @@
// Extra methods for subclasses that need to perform extra work on initialization/destruction.
public void initialize() {}
+
public void destroy() {}
}
diff --git a/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java b/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java
index a6a2aba..75e36e3 100644
--- a/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java
+++ b/base/android/java/src/org/chromium/base/jank_tracker/PlaceholderJankTracker.java
@@ -4,9 +4,7 @@
package org.chromium.base.jank_tracker;
-/**
- * Placeholder implementation of JankTracker.
- */
+/** Placeholder implementation of JankTracker. */
public class PlaceholderJankTracker implements JankTracker {
@Override
public void startTrackingScenario(int scenario) {}
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
index 57dc74c..005ec73 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryLoader.java
@@ -105,6 +105,7 @@
int MAIN_DEX_LOADED = 1;
int LOADED = 2;
}
+
private volatile @LoadState int mLoadState;
// Tracks mLoadState, but can be reset to NOT_LOADED between tests to ensure that each test that
@@ -163,8 +164,7 @@
// Used by tests to ensure that sLoadFailedCallback is called, also referenced by
// SplitCompatApplication.
- @VisibleForTesting
- public static boolean sOverrideNativeLibraryCannotBeLoadedForTesting;
+ @VisibleForTesting public static boolean sOverrideNativeLibraryCannotBeLoadedForTesting;
// Allow embedders to register a callback to handle native library load failures.
public static Callback<UnsatisfiedLinkError> sLoadFailedCallback;
@@ -248,18 +248,25 @@
// because waiting for zygote to reveal its address would have
// delayed startup.
if (DEBUG) {
- Log.i(TAG, "ensureInitializedInMainProcess, producing RELRO FD: %b",
+ Log.i(
+ TAG,
+ "ensureInitializedInMainProcess, producing RELRO FD: %b",
attemptProduceRelro);
}
// For devices avoiding the App Zygote in
- // ChildConnectionAllocator.createVariableSize() the FIND_RESERVED search can be
- // avoided: a random region is sufficient. TODO(pasko): Investigate whether it is
- // worth coordinating with the ChildConnectionAllocator. To speed up process
- // creation.
- int preferAddress = attemptProduceRelro ? Linker.PreferAddress.RESERVE_RANDOM
- : Linker.PreferAddress.FIND_RESERVED;
- getLinker().ensureInitialized(
- attemptProduceRelro, preferAddress, /* addressHint= */ 0);
+ // ChildConnectionAllocator.createVariableSize()
+ // the FIND_RESERVED search can be avoided: a random region is sufficient.
+ // TODO(pasko):
+ // Investigate whether it is worth coordinating with the ChildConnectionAllocator.
+ // To
+ // speed up process creation.
+ int preferAddress =
+ attemptProduceRelro
+ ? Linker.PreferAddress.RESERVE_RANDOM
+ : Linker.PreferAddress.FIND_RESERVED;
+ getLinker()
+ .ensureInitialized(
+ attemptProduceRelro, preferAddress, /* addressHint= */ 0);
}
mCreatedIn = CreatedIn.MAIN;
mInitDone = true;
@@ -284,8 +291,9 @@
public void initInAppZygote() {
assert !mInitDone;
if (useChromiumLinker() && !mainProcessIntendsToProvideRelroFd()) {
- getLinker().ensureInitialized(
- /* asRelroProducer= */ true, Linker.PreferAddress.FIND_RESERVED, 0);
+ getLinker()
+ .ensureInitialized(
+ /* asRelroProducer= */ true, Linker.PreferAddress.FIND_RESERVED, 0);
} else {
// The main process will attempt to create RELRO FD without coordination. Fall back
// to loading with the system linker. Can happen in tests and on dev builds with
@@ -310,11 +318,15 @@
if (DEBUG) {
Log.i(TAG, "initInChildProcess: RELRO FD not provided by App Zygote");
}
- getLinker().ensureInitialized(/* asRelroProducer= */ false,
- Linker.PreferAddress.RESERVE_HINT, getLoadAddress());
+ getLinker()
+ .ensureInitialized(
+ /* asRelroProducer= */ false,
+ Linker.PreferAddress.RESERVE_HINT,
+ getLoadAddress());
} else if (isLoadedByZygote()) {
if (DEBUG) {
- Log.i(TAG,
+ Log.i(
+ TAG,
"initInChildProcess: already loaded by app zygote "
+ "(mFallbackToSystemLinker=%b)",
mFallbackToSystemLinker);
@@ -323,8 +335,11 @@
if (DEBUG) {
Log.i(TAG, "initInChildProcess: the app zygote failed to produce RELRO FD");
}
- getLinker().ensureInitialized(/* asRelroProducer= */ false,
- Linker.PreferAddress.RESERVE_HINT, getLoadAddress());
+ getLinker()
+ .ensureInitialized(
+ /* asRelroProducer= */ false,
+ Linker.PreferAddress.RESERVE_HINT,
+ getLoadAddress());
} else {
// The main process expects the app zygote to provide the RELRO FD, but this process
// does not inherit from the app zygote. This could be because:
@@ -337,13 +352,17 @@
// TODO(pasko): Investigate whether searching with FIND_RESERVED affects startup
// speed on Go devices.
if (DEBUG) {
- Log.i(TAG,
+ Log.i(
+ TAG,
"initInChildProcess: child process not from app zygote, with address "
+ "hint: 0x%x",
getLoadAddress());
}
- getLinker().ensureInitialized(/* asRelroProducer= */ false,
- Linker.PreferAddress.FIND_RESERVED, getLoadAddress());
+ getLinker()
+ .ensureInitialized(
+ /* asRelroProducer= */ false,
+ Linker.PreferAddress.FIND_RESERVED,
+ getLoadAddress());
}
if (mCreatedIn != CreatedIn.ZYGOTE) mCreatedIn = CreatedIn.CHILD_WITHOUT_ZYGOTE;
mInitDone = true;
@@ -414,12 +433,13 @@
logLinkerUsed();
}
if (BuildConfig.ENABLE_ASSERTS) {
- NativeLibraryLoadedStatus.setProvider(new NativeLibraryLoadedStatusProvider() {
- @Override
- public boolean areNativeMethodsReady() {
- return isMainDexLoaded();
- }
- });
+ NativeLibraryLoadedStatus.setProvider(
+ new NativeLibraryLoadedStatusProvider() {
+ @Override
+ public boolean areNativeMethodsReady() {
+ return isMainDexLoaded();
+ }
+ });
}
}
@@ -435,7 +455,8 @@
if (type == mLibraryProcessType) return;
if (mLibraryProcessType != LibraryProcessType.PROCESS_UNINITIALIZED) {
throw new IllegalStateException(
- String.format("Trying to change the LibraryProcessType from %d to %d",
+ String.format(
+ "Trying to change the LibraryProcessType from %d to %d",
mLibraryProcessType, type));
}
mLibraryProcessType = type;
@@ -502,9 +523,7 @@
}
}
- /**
- * Return if library is already loaded successfully by the zygote.
- */
+ /** Return if library is already loaded successfully by the zygote. */
public boolean isLoadedByZygote() {
synchronized (mLock) {
return mLoadedByZygote;
@@ -552,9 +571,7 @@
ContextUtils.getApplicationContext().getApplicationInfo().packageName);
}
- /**
- * Similar to {@link #preloadNow}, but allows specifying app context to use.
- */
+ /** Similar to {@link #preloadNow}, but allows specifying app context to use. */
public void preloadNowOverridePackageName(String packageName) {
synchronized (mLock) {
if (useChromiumLinker()) return;
@@ -612,9 +629,7 @@
loadNowOverrideApplicationContext(ContextUtils.getApplicationContext());
}
- /**
- * Causes LibraryLoader to pretend that native libraries have not yet been initialized.
- */
+ /** Causes LibraryLoader to pretend that native libraries have not yet been initialized. */
public void resetForTesting() {
mLoadStateForTesting = LoadState.NOT_LOADED;
mInitializedForTesting = false;
@@ -690,12 +705,12 @@
@VisibleForTesting
public static int getReachedCodeSamplingIntervalUs() {
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
- if (ContextUtils.getAppSharedPreferences().getBoolean(
- DEPRECATED_REACHED_CODE_PROFILER_KEY, false)) {
+ if (ContextUtils.getAppSharedPreferences()
+ .getBoolean(DEPRECATED_REACHED_CODE_PROFILER_KEY, false)) {
return DEFAULT_REACHED_CODE_SAMPLING_INTERVAL_US;
}
- return ContextUtils.getAppSharedPreferences().getInt(
- REACHED_CODE_SAMPLING_INTERVAL_KEY, 0);
+ return ContextUtils.getAppSharedPreferences()
+ .getInt(REACHED_CODE_SAMPLING_INTERVAL_KEY, 0);
}
}
@@ -721,8 +736,8 @@
@VisibleForTesting
public static boolean isBackgroundThreadPoolEnabled() {
try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) {
- return ContextUtils.getAppSharedPreferences().getBoolean(
- BACKGROUND_THREAD_POOL_KEY, false);
+ return ContextUtils.getAppSharedPreferences()
+ .getBoolean(BACKGROUND_THREAD_POOL_KEY, false);
}
}
@@ -855,9 +870,10 @@
int reachedCodeSamplingIntervalUs = getReachedCodeSamplingIntervalUs();
if (reachedCodeSamplingIntervalUs > 0) {
CommandLine.getInstance().appendSwitch(BaseSwitches.ENABLE_REACHED_CODE_PROFILER);
- CommandLine.getInstance().appendSwitchWithValue(
- BaseSwitches.REACHED_CODE_SAMPLING_INTERVAL_US,
- Integer.toString(reachedCodeSamplingIntervalUs));
+ CommandLine.getInstance()
+ .appendSwitchWithValue(
+ BaseSwitches.REACHED_CODE_SAMPLING_INTERVAL_US,
+ Integer.toString(reachedCodeSamplingIntervalUs));
}
// Similarly, append a switch to enable the background thread pool group if the cached
@@ -921,7 +937,8 @@
if (BuildConfig.IS_UBSAN) {
try {
// This value is duplicated in build/android/pylib/constants/__init__.py.
- Os.setenv("UBSAN_OPTIONS",
+ Os.setenv(
+ "UBSAN_OPTIONS",
"print_stacktrace=1 stack_trace_format='#%n pc %o %m' "
+ "handle_segv=0 handle_sigbus=0 handle_sigfpe=0",
true);
diff --git a/base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java b/base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java
index cd2353c..6fbab7e 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LibraryPrefetcher.java
@@ -27,8 +27,7 @@
public class LibraryPrefetcher {
private static final String TAG = "LibraryPrefetcher";
- // One-way switch that becomes true once
- // {@link asyncPrefetchLibrariesToMemory} has been called.
+ // One-way switch that becomes true once {@link asyncPrefetchLibrariesToMemory} has been called.
private static final AtomicBoolean sPrefetchLibraryHasBeenCalled = new AtomicBoolean();
/**
@@ -55,24 +54,33 @@
return;
}
- PostTask.postTask(TaskTraits.USER_BLOCKING, () -> {
- int percentage = LibraryPrefetcherJni.get().percentageOfResidentNativeLibraryCode();
- try (TraceEvent e =
- TraceEvent.scoped("LibraryPrefetcher.asyncPrefetchLibrariesToMemory",
+ PostTask.postTask(
+ TaskTraits.USER_BLOCKING,
+ () -> {
+ int percentage =
+ LibraryPrefetcherJni.get().percentageOfResidentNativeLibraryCode();
+ try (TraceEvent e =
+ TraceEvent.scoped(
+ "LibraryPrefetcher.asyncPrefetchLibrariesToMemory",
Integer.toString(percentage))) {
- // Arbitrary percentage threshold. If most of the native library is already
- // resident (likely with monochrome), don't bother creating a prefetch process.
- boolean prefetch = coldStart && percentage < 90;
- if (prefetch) LibraryPrefetcherJni.get().forkAndPrefetchNativeLibrary();
- if (percentage != -1) {
- String histogram = "LibraryLoader.PercentageOfResidentCodeBeforePrefetch"
- + (coldStart ? ".ColdStartup" : ".WarmStartup");
- RecordHistogram.recordPercentageHistogram(histogram, percentage);
- }
- }
- // Removes a dead flag, don't remove the removal code before M77 at least.
- ContextUtils.getAppSharedPreferences().edit().remove("dont_prefetch_libraries").apply();
- });
+ // Arbitrary percentage threshold. If most of the native library is already
+ // resident (likely with monochrome), don't bother creating a prefetch
+ // process.
+ boolean prefetch = coldStart && percentage < 90;
+ if (prefetch) LibraryPrefetcherJni.get().forkAndPrefetchNativeLibrary();
+ if (percentage != -1) {
+ String histogram =
+ "LibraryLoader.PercentageOfResidentCodeBeforePrefetch"
+ + (coldStart ? ".ColdStartup" : ".WarmStartup");
+ RecordHistogram.recordPercentageHistogram(histogram, percentage);
+ }
+ }
+ // Removes a dead flag, don't remove the removal code before M77 at least.
+ ContextUtils.getAppSharedPreferences()
+ .edit()
+ .remove("dont_prefetch_libraries")
+ .apply();
+ });
}
@NativeMethods
diff --git a/base/android/java/src/org/chromium/base/library_loader/Linker.java b/base/android/java/src/org/chromium/base/library_loader/Linker.java
index 379a724..70b176b 100644
--- a/base/android/java/src/org/chromium/base/library_loader/Linker.java
+++ b/base/android/java/src/org/chromium/base/library_loader/Linker.java
@@ -80,6 +80,7 @@
// Constants used to pass the shared RELRO Bundle through Binder.
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
static final String SHARED_RELROS = "org.chromium.base.android.linker.shared_relros";
+
private static final String BASE_LOAD_ADDRESS =
"org.chromium.base.android.linker.base_load_address";
@@ -168,6 +169,7 @@
int RESERVE_HINT = 1;
int RESERVE_RANDOM = 2;
}
+
private String preferAddressToString(@PreferAddress int a) {
switch (a) {
case PreferAddress.FIND_RESERVED:
@@ -230,15 +232,16 @@
final void ensureInitialized(
boolean asRelroProducer, @PreferAddress int preference, long addressHint) {
if (DEBUG) {
- Log.i(TAG,
+ Log.i(
+ TAG,
"ensureInitialized(asRelroProducer=%b, preference=%s, "
+ "loadAddressHint=0x%x)",
- asRelroProducer, preferAddressToString(preference), addressHint);
+ asRelroProducer,
+ preferAddressToString(preference),
+ addressHint);
}
- assert !asRelroProducer
- || preference
- != PreferAddress.RESERVE_HINT
- : "Producer does not accept hints from outside";
+ assert !asRelroProducer || preference != PreferAddress.RESERVE_HINT
+ : "Producer does not accept hints from outside";
synchronized (mLock) {
if (mState != State.UNINITIALIZED) return;
chooseAndReserveMemoryRange(asRelroProducer, preference, addressHint);
@@ -347,8 +350,11 @@
assert !library.equals(LINKER_JNI_LIBRARY);
loadLibraryImplLocked(library, relroMode);
if (DEBUG) {
- Log.i(TAG, "Attempt to replace RELRO: remotenonnull=%b, state=%d",
- mRemoteLibInfo != null, mState);
+ Log.i(
+ TAG,
+ "Attempt to replace RELRO: remotenonnull=%b, state=%d",
+ mRemoteLibInfo != null,
+ mState);
}
if (shouldAtomicallyReplaceRelroAfterLoad()) {
atomicReplaceRelroLocked(/* relroAvailableImmediately= */ true);
@@ -373,7 +379,8 @@
// Load the library. During initialization Linker subclass reserves the address
// range where the library will be loaded and keeps it in |mLocalLibInfo|.
- attemptLoadLibraryLocked(library,
+ attemptLoadLibraryLocked(
+ library,
mRelroProducer ? RelroSharingMode.PRODUCE : RelroSharingMode.CONSUME);
} catch (UnsatisfiedLinkError e) {
Log.w(TAG, "Failed to load native library with shared RELRO, retrying without");
@@ -403,10 +410,12 @@
}
bundle.putBundle(SHARED_RELROS, relros);
if (DEBUG && relros != null) {
- Log.i(TAG,
+ Log.i(
+ TAG,
"putSharedRelrosToBundle() puts mLoadAddress=0x%x, mLoadSize=%d, "
+ "mRelroFd=%d",
- mLocalLibInfo.mLoadAddress, mLocalLibInfo.mLoadSize,
+ mLocalLibInfo.mLoadAddress,
+ mLocalLibInfo.mLoadSize,
mLocalLibInfo.mRelroFd);
}
}
@@ -427,10 +436,12 @@
synchronized (mLock) {
if (mRemoteLibInfo != null && mRemoteLibInfo.mRelroFd != -1) {
if (DEBUG) {
- Log.i(TAG,
+ Log.i(
+ TAG,
"Attempt to replace RELRO a second time "
+ "library addr=0x%x, with new library addr=0x%x",
- mRemoteLibInfo.mLoadAddress, newRemote.mLoadAddress);
+ mRemoteLibInfo.mLoadAddress,
+ newRemote.mLoadAddress);
}
return;
}
@@ -441,8 +452,11 @@
}
}
- @IntDef({Linker.RelroSharingMode.NO_SHARING, Linker.RelroSharingMode.PRODUCE,
- Linker.RelroSharingMode.CONSUME})
+ @IntDef({
+ Linker.RelroSharingMode.NO_SHARING,
+ Linker.RelroSharingMode.PRODUCE,
+ Linker.RelroSharingMode.CONSUME
+ })
@Retention(RetentionPolicy.SOURCE)
private @interface RelroSharingMode {
// Do not attempt to create or use a RELRO region.
@@ -460,7 +474,8 @@
@GuardedBy("mLock")
private void loadWithoutProducingRelro(String libFilePath) {
assert mRemoteLibInfo == null || libFilePath.equals(mRemoteLibInfo.mLibFilePath);
- if (!getLinkerJni().loadLibrary(libFilePath, mLocalLibInfo, false /* spawnRelroRegion */)) {
+ if (!getLinkerJni()
+ .loadLibrary(libFilePath, mLocalLibInfo, /* spawnRelroRegion= */ false)) {
resetAndThrow(String.format("Unable to load library: %s", libFilePath), null);
}
assert mLocalLibInfo.mRelroFd == -1;
@@ -471,10 +486,13 @@
@GuardedBy("mLock")
private void loadAndProduceSharedRelro(String libFilePath) {
mLocalLibInfo.mLibFilePath = libFilePath;
- if (getLinkerJni().loadLibrary(libFilePath, mLocalLibInfo, true /* spawnRelroRegion */)) {
+ if (getLinkerJni().loadLibrary(libFilePath, mLocalLibInfo, /* spawnRelroRegion= */ true)) {
if (DEBUG) {
- Log.i(TAG, "Successfully spawned RELRO: mLoadAddress=0x%x, mLoadSize=%d",
- mLocalLibInfo.mLoadAddress, mLocalLibInfo.mLoadSize);
+ Log.i(
+ TAG,
+ "Successfully spawned RELRO: mLoadAddress=0x%x, mLoadSize=%d",
+ mLocalLibInfo.mLoadAddress,
+ mLocalLibInfo.mLoadSize);
}
} else {
Log.e(TAG, "Unable to load with Linker, using the system linker instead");
@@ -553,8 +571,11 @@
assert mState == State.DONE;
if (mRemoteLibInfo.mRelroFd == -1) return;
if (DEBUG) {
- Log.i(TAG, "Received mRemoteLibInfo: mLoadAddress=0x%x, mLoadSize=%d",
- mRemoteLibInfo.mLoadAddress, mRemoteLibInfo.mLoadSize);
+ Log.i(
+ TAG,
+ "Received mRemoteLibInfo: mLoadAddress=0x%x, mLoadSize=%d",
+ mRemoteLibInfo.mLoadAddress,
+ mRemoteLibInfo.mLoadSize);
}
if (mLocalLibInfo == null) return;
getLinkerJni().useRelros(mLocalLibInfo.mLoadAddress, mRemoteLibInfo);
@@ -704,16 +725,11 @@
// IMPORTANT: Don't change these fields without modifying the
// native code that accesses them directly!
- @AccessedByNative
- public long mLoadAddress; // page-aligned library load address.
- @AccessedByNative
- public long mLoadSize; // page-aligned library load size.
- @AccessedByNative
- public long mRelroStart; // page-aligned address in memory, or 0 if none.
- @AccessedByNative
- public long mRelroSize; // page-aligned size in memory, or 0.
- @AccessedByNative
- public int mRelroFd = -1; // shared RELRO file descriptor, or -1
+ @AccessedByNative public long mLoadAddress; // page-aligned library load address.
+ @AccessedByNative public long mLoadSize; // page-aligned library load size.
+ @AccessedByNative public long mRelroStart; // page-aligned address in memory, or 0 if none.
+ @AccessedByNative public long mRelroSize; // page-aligned size in memory, or 0.
+ @AccessedByNative public int mRelroFd = -1; // shared RELRO file descriptor, or -1
}
interface Natives {
diff --git a/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java b/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java
index b9e3820..981650d 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LinkerJni.java
@@ -48,12 +48,17 @@
// libmonochrome.so
private static native void nativeFindMemoryRegionAtRandomAddress(
@NonNull Linker.LibInfo libInfo);
+
private static native void nativeReserveMemoryForLibrary(@NonNull Linker.LibInfo libInfo);
+
private static native boolean nativeFindRegionReservedByWebViewZygote(
@NonNull Linker.LibInfo libInfo);
+
private static native boolean nativeLoadLibrary(
String libFilePath, Linker.LibInfo libInfo, boolean spawnRelroRegion);
+
private static native boolean nativeUseRelros(
long localLoadAddress, Linker.LibInfo remoteLibInfo);
+
private static native int nativeGetRelroSharingResult();
}
diff --git a/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java b/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java
index d059de5..43523bb 100644
--- a/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java
+++ b/base/android/java/src/org/chromium/base/library_loader/LoaderErrors.java
@@ -9,12 +9,14 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-/**
- * These are the possible failures from the LibraryLoader
- */
-@IntDef({LoaderErrors.NORMAL_COMPLETION, LoaderErrors.FAILED_TO_REGISTER_JNI,
- LoaderErrors.NATIVE_LIBRARY_LOAD_FAILED, LoaderErrors.NATIVE_LIBRARY_WRONG_VERSION,
- LoaderErrors.NATIVE_STARTUP_FAILED})
+/** These are the possible failures from the LibraryLoader */
+@IntDef({
+ LoaderErrors.NORMAL_COMPLETION,
+ LoaderErrors.FAILED_TO_REGISTER_JNI,
+ LoaderErrors.NATIVE_LIBRARY_LOAD_FAILED,
+ LoaderErrors.NATIVE_LIBRARY_WRONG_VERSION,
+ LoaderErrors.NATIVE_STARTUP_FAILED
+})
@Retention(RetentionPolicy.SOURCE)
public @interface LoaderErrors {
int NORMAL_COMPLETION = 0;
diff --git a/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java b/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java
index 0711910..6e7f422 100644
--- a/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java
+++ b/base/android/java/src/org/chromium/base/library_loader/ProcessInitException.java
@@ -4,9 +4,7 @@
package org.chromium.base.library_loader;
-/**
- * The exception that is thrown when the initialization of a process has failed.
- */
+/** The exception that is thrown when the initialization of a process has failed. */
public class ProcessInitException extends RuntimeException {
/**
* @param errorCode This will be one of the LoaderErrors error codes.
diff --git a/base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java b/base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java
index d23da76..9e78c12 100644
--- a/base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java
+++ b/base/android/java/src/org/chromium/base/memory/JavaHeapDumpGenerator.java
@@ -12,11 +12,10 @@
import java.io.IOException;
-/**
- * Enables the generation of hprof files from heap dumps.
- */
+/** Enables the generation of hprof files from heap dumps. */
public final class JavaHeapDumpGenerator {
private static final String TAG = "JavaHprofGenerator";
+
private JavaHeapDumpGenerator() {}
/**
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryInfoBridge.java b/base/android/java/src/org/chromium/base/memory/MemoryInfoBridge.java
index 7f39289..7cd8cb3 100644
--- a/base/android/java/src/org/chromium/base/memory/MemoryInfoBridge.java
+++ b/base/android/java/src/org/chromium/base/memory/MemoryInfoBridge.java
@@ -15,9 +15,7 @@
import org.chromium.base.ContextUtils;
-/**
- * Allows calling ActivityManager#getProcessMemoryInfo() from native.
- */
+/** Allows calling ActivityManager#getProcessMemoryInfo() from native. */
public class MemoryInfoBridge {
/**
* Returns the result of ActivityManager#getProcessMemoryInfo() on itself.
@@ -29,8 +27,9 @@
@CalledByNative
public static @Nullable Debug.MemoryInfo getActivityManagerMemoryInfoForSelf() {
ActivityManager activityManager =
- (ActivityManager) ContextUtils.getApplicationContext().getSystemService(
- Context.ACTIVITY_SERVICE);
+ (ActivityManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.ACTIVITY_SERVICE);
int pid = Process.myPid();
try {
Debug.MemoryInfo[] infos = activityManager.getProcessMemoryInfo(new int[] {pid});
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java
index 46e50b2..fd8a0b8 100644
--- a/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java
+++ b/base/android/java/src/org/chromium/base/memory/MemoryPressureCallback.java
@@ -6,9 +6,7 @@
import org.chromium.base.MemoryPressureLevel;
-/**
- * Memory pressure callback interface.
- */
+/** Memory pressure callback interface. */
@FunctionalInterface
public interface MemoryPressureCallback {
public void onPressure(@MemoryPressureLevel int pressure);
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java
index 800ac36..c8135ee 100644
--- a/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java
+++ b/base/android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java
@@ -90,7 +90,7 @@
private Supplier<Integer> mCurrentPressureSupplierForTesting;
private MemoryPressureCallback mReportingCallbackForTesting;
- private final Runnable mThrottlingIntervalTask = this ::onThrottlingIntervalFinished;
+ private final Runnable mThrottlingIntervalTask = this::onThrottlingIntervalFinished;
// The only instance.
public static final MemoryPressureMonitor INSTANCE =
@@ -101,29 +101,29 @@
mThrottlingIntervalMs = throttlingIntervalMs;
}
- /**
- * Starts listening to ComponentCallbacks2.
- */
+ /** Starts listening to ComponentCallbacks2. */
public void registerComponentCallbacks() {
ThreadUtils.assertOnUiThread();
- ContextUtils.getApplicationContext().registerComponentCallbacks(new ComponentCallbacks2() {
- @Override
- public void onTrimMemory(int level) {
- Integer pressure = memoryPressureFromTrimLevel(level);
- if (pressure != null) {
- notifyPressure(pressure);
- }
- }
+ ContextUtils.getApplicationContext()
+ .registerComponentCallbacks(
+ new ComponentCallbacks2() {
+ @Override
+ public void onTrimMemory(int level) {
+ Integer pressure = memoryPressureFromTrimLevel(level);
+ if (pressure != null) {
+ notifyPressure(pressure);
+ }
+ }
- @Override
- public void onLowMemory() {
- notifyPressure(MemoryPressureLevel.CRITICAL);
- }
+ @Override
+ public void onLowMemory() {
+ notifyPressure(MemoryPressureLevel.CRITICAL);
+ }
- @Override
- public void onConfigurationChanged(Configuration configuration) {}
- });
+ @Override
+ public void onConfigurationChanged(Configuration configuration) {}
+ });
}
/**
@@ -141,9 +141,7 @@
}
}
- /**
- * Disables memory pressure polling.
- */
+ /** Disables memory pressure polling. */
public void disablePolling() {
ThreadUtils.assertOnUiThread();
if (!mPollingEnabled) return;
@@ -210,9 +208,10 @@
}
private void reportCurrentPressure() {
- Integer pressure = mCurrentPressureSupplierForTesting != null
- ? mCurrentPressureSupplierForTesting.get()
- : MemoryPressureMonitor.getCurrentMemoryPressure();
+ Integer pressure =
+ mCurrentPressureSupplierForTesting != null
+ ? mCurrentPressureSupplierForTesting.get()
+ : MemoryPressureMonitor.getCurrentMemoryPressure();
if (pressure != null) {
reportPressure(pressure);
}
@@ -238,8 +237,8 @@
* Returns null if the pressure couldn't be determined.
*/
private static @MemoryPressureLevel Integer getCurrentMemoryPressure() {
- // We used to have a histogram here to measure the duration of each successful
- // ActivityManager.getMyMemoryState() call called
+ // We used to have a histogram here to measure the duration of each successful
+ // ActivityManager.getMyMemoryState() call called
// Android.MemoryPressureMonitor.GetMyMemoryState.Succeeded.Time. 50th percentile was 0.8ms.
try {
ActivityManager.RunningAppProcessInfo processInfo =
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java b/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java
index 1bb20c5..355bf8c 100644
--- a/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java
+++ b/base/android/java/src/org/chromium/base/memory/MemoryPressureUma.java
@@ -16,15 +16,19 @@
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-/**
- * Centralizes UMA data collection for Android-specific memory conditions.
- */
+/** Centralizes UMA data collection for Android-specific memory conditions. */
public class MemoryPressureUma implements ComponentCallbacks2 {
- @IntDef({Notification.UNKNOWN_TRIM_LEVEL, Notification.TRIM_MEMORY_COMPLETE,
- Notification.TRIM_MEMORY_MODERATE, Notification.TRIM_MEMORY_BACKGROUND,
- Notification.TRIM_MEMORY_UI_HIDDEN, Notification.TRIM_MEMORY_RUNNING_CRITICAL,
- Notification.TRIM_MEMORY_RUNNING_LOW, Notification.TRIM_MEMORY_RUNNING_MODERATE,
- Notification.ON_LOW_MEMORY})
+ @IntDef({
+ Notification.UNKNOWN_TRIM_LEVEL,
+ Notification.TRIM_MEMORY_COMPLETE,
+ Notification.TRIM_MEMORY_MODERATE,
+ Notification.TRIM_MEMORY_BACKGROUND,
+ Notification.TRIM_MEMORY_UI_HIDDEN,
+ Notification.TRIM_MEMORY_RUNNING_CRITICAL,
+ Notification.TRIM_MEMORY_RUNNING_LOW,
+ Notification.TRIM_MEMORY_RUNNING_MODERATE,
+ Notification.ON_LOW_MEMORY
+ })
@Retention(RetentionPolicy.SOURCE)
private @interface Notification {
// WARNING: These values are persisted to logs. Entries should not be
diff --git a/base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java b/base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java
index 1d5fcb1..d640bf7 100644
--- a/base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java
+++ b/base/android/java/src/org/chromium/base/memory/MemoryPurgeManager.java
@@ -33,9 +33,9 @@
// for freezing.
// TODO(crbug.com/1356242): Should ideally be tuned according to the distribution of background
// time residency.
- @VisibleForTesting
- static final long PURGE_DELAY_MS = 4 * 60 * 1000;
+ @VisibleForTesting static final long PURGE_DELAY_MS = 4 * 60 * 1000;
private static final long NEVER = -1;
+
@VisibleForTesting
static final String BACKGROUND_DURATION_HISTOGRAM_NAME =
"Android.ApplicationState.TimeInBackgroundBeforeForegroundedAgain";
@@ -122,10 +122,12 @@
ThreadUtils.assertOnUiThread();
if (mDelayedPurgeTaskPending) return;
- ThreadUtils.postOnUiThreadDelayed(() -> {
- mDelayedPurgeTaskPending = false;
- delayedPurge();
- }, delayMillis);
+ ThreadUtils.postOnUiThreadDelayed(
+ () -> {
+ mDelayedPurgeTaskPending = false;
+ delayedPurge();
+ },
+ delayMillis);
mDelayedPurgeTaskPending = true;
}
}
diff --git a/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java
index 5f9658d..9343cde 100644
--- a/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java
+++ b/base/android/java/src/org/chromium/base/metrics/CachingUmaRecorder.java
@@ -48,52 +48,40 @@
* Maximum number of user actions cached at the same time. It is better to drop some samples
* rather than have a bug cause the cache to grow without limit.
*/
- @VisibleForTesting
- static final int MAX_USER_ACTION_COUNT = 256;
+ @VisibleForTesting static final int MAX_USER_ACTION_COUNT = 256;
/** Stores the definition and samples of a single cached histogram. */
@VisibleForTesting
static class Histogram {
/**
- * Maximum number of cached samples in a single histogram. it is better to drop some
- * samples rather than have a bug cause the cache to grow without limit
+ * Maximum number of cached samples in a single histogram. it is better to drop some samples
+ * rather than have a bug cause the cache to grow without limit
*/
- @VisibleForTesting
- static final int MAX_SAMPLE_COUNT = 256;
+ @VisibleForTesting static final int MAX_SAMPLE_COUNT = 256;
- /**
- * Identifies the type of the histogram.
- */
+ /** Identifies the type of the histogram. */
@IntDef({
- Type.BOOLEAN,
- Type.EXPONENTIAL,
- Type.LINEAR,
- Type.SPARSE,
+ Type.BOOLEAN,
+ Type.EXPONENTIAL,
+ Type.LINEAR,
+ Type.SPARSE,
})
@Retention(RetentionPolicy.SOURCE)
@interface Type {
- /**
- * Used by histograms recorded with {@link UmaRecorder#recordBooleanHistogram}.
- */
+ /** Used by histograms recorded with {@link UmaRecorder#recordBooleanHistogram}. */
int BOOLEAN = 1;
- /**
- * Used by histograms recorded with {@link UmaRecorder#recordExponentialHistogram}.
- */
+
+ /** Used by histograms recorded with {@link UmaRecorder#recordExponentialHistogram}. */
int EXPONENTIAL = 2;
- /**
- * Used by histograms recorded with {@link UmaRecorder#recordLinearHistogram}.
- */
+ /** Used by histograms recorded with {@link UmaRecorder#recordLinearHistogram}. */
int LINEAR = 3;
- /**
- * Used by histograms recorded with {@link UmaRecorder#recordSparseHistogram}.
- */
+ /** Used by histograms recorded with {@link UmaRecorder#recordSparseHistogram}. */
int SPARSE = 4;
}
- @Type
- private final int mType;
+ @Type private final int mType;
private final String mName;
private final int mMin;
@@ -114,16 +102,17 @@
* histograms.
*/
Histogram(@Type int type, String name, int min, int max, int numBuckets) {
- assert type == Type.EXPONENTIAL || type == Type.LINEAR
- || (min == 0 && max == 0 && numBuckets == 0)
- : "Histogram type " + type + " must have no min/max/buckets set";
+ assert type == Type.EXPONENTIAL
+ || type == Type.LINEAR
+ || (min == 0 && max == 0 && numBuckets == 0)
+ : "Histogram type " + type + " must have no min/max/buckets set";
mType = type;
mName = name;
mMin = min;
mMax = max;
mNumBuckets = numBuckets;
- mSamples = new ArrayList<>(/*initialCapacity=*/1);
+ mSamples = new ArrayList<>(/* initialCapacity= */ 1);
}
/**
@@ -216,11 +205,11 @@
/**
* The lock doesn't need to be fair - in the worst case a writing record*Histogram call will be
* starved until reading calls reach cache size limits.
- * <p>
- * A read-write lock is used rather than {@code synchronized} blocks to the limit opportunities
- * for stutter on the UI thread when waiting for this shared resource.
+ *
+ * <p>A read-write lock is used rather than {@code synchronized} blocks to the limit
+ * opportunities for stutter on the UI thread when waiting for this shared resource.
*/
- private final ReentrantReadWriteLock mRwLock = new ReentrantReadWriteLock(/*fair=*/false);
+ private final ReentrantReadWriteLock mRwLock = new ReentrantReadWriteLock(/* fair= */ false);
/** Cached histograms keyed by histogram name. */
@GuardedBy("mRwLock")
@@ -330,8 +319,12 @@
for (Histogram histogram : cache.values()) {
flushedHistogramSampleCount += histogram.flushTo(mDelegate);
}
- Log.i(TAG, "Flushed %d samples from %d histograms, %d samples were dropped.",
- flushedHistogramSampleCount, flushedHistogramCount, droppedHistogramSampleCount);
+ Log.i(
+ TAG,
+ "Flushed %d samples from %d histograms, %d samples were dropped.",
+ flushedHistogramSampleCount,
+ flushedHistogramCount,
+ droppedHistogramSampleCount);
}
/**
@@ -348,7 +341,10 @@
for (UserAction userAction : cache) {
userAction.flushTo(mDelegate);
}
- Log.i(TAG, "Flushed %d user action samples, %d samples were dropped.", cache.size(),
+ Log.i(
+ TAG,
+ "Flushed %d user action samples, %d samples were dropped.",
+ cache.size(),
droppedUserActionCount);
}
@@ -616,7 +612,7 @@
}
Arrays.sort(samplesCopy);
List<HistogramBucket> buckets = new ArrayList<>();
- for (int i = 0; i < samplesCopy.length;) {
+ for (int i = 0; i < samplesCopy.length; ) {
int value = samplesCopy[i];
int countInBucket = 0;
do {
@@ -653,8 +649,9 @@
mRwLock.writeLock().lock();
try {
if (mUserActionCallbacksForTesting == null) {
- assert false : "Attempting to remove a user action callback without previously "
- + "registering any.";
+ assert false
+ : "Attempting to remove a user action callback without previously "
+ + "registering any.";
return;
}
mUserActionCallbacksForTesting.remove(callback);
diff --git a/base/android/java/src/org/chromium/base/metrics/HistogramBucket.java b/base/android/java/src/org/chromium/base/metrics/HistogramBucket.java
index 8a55a39..2f9aab6 100644
--- a/base/android/java/src/org/chromium/base/metrics/HistogramBucket.java
+++ b/base/android/java/src/org/chromium/base/metrics/HistogramBucket.java
@@ -4,9 +4,7 @@
package org.chromium.base.metrics;
-/**
- * Represents one single bucket of a histogram, with the count of records in that bucket.
- */
+/** Represents one single bucket of a histogram, with the count of records in that bucket. */
public class HistogramBucket {
public final int mMin;
public final long mMax;
diff --git a/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java b/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java
index fb7b7be..d14409f 100644
--- a/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java
+++ b/base/android/java/src/org/chromium/base/metrics/NativeUmaRecorder.java
@@ -32,6 +32,7 @@
*/
private final Map<String, Long> mNativeHints =
Collections.synchronizedMap(new HashMap<String, Long>());
+
private Map<Callback<String>, Long> mUserActionTestingCallbackNativePtrs;
@Override
@@ -45,16 +46,18 @@
public void recordExponentialHistogram(
String name, int sample, int min, int max, int numBuckets) {
long oldHint = getNativeHint(name);
- long newHint = NativeUmaRecorderJni.get().recordExponentialHistogram(
- name, oldHint, sample, min, max, numBuckets);
+ long newHint =
+ NativeUmaRecorderJni.get()
+ .recordExponentialHistogram(name, oldHint, sample, min, max, numBuckets);
maybeUpdateNativeHint(name, oldHint, newHint);
}
@Override
public void recordLinearHistogram(String name, int sample, int min, int max, int numBuckets) {
long oldHint = getNativeHint(name);
- long newHint = NativeUmaRecorderJni.get().recordLinearHistogram(
- name, oldHint, sample, min, max, numBuckets);
+ long newHint =
+ NativeUmaRecorderJni.get()
+ .recordLinearHistogram(name, oldHint, sample, min, max, numBuckets);
maybeUpdateNativeHint(name, oldHint, newHint);
}
@@ -108,13 +111,15 @@
public void removeUserActionCallbackForTesting(Callback<String> callback) {
if (mUserActionTestingCallbackNativePtrs == null) {
assert false
- : "Attempting to remove a user action callback without previously registering any.";
+ : "Attempting to remove a user action callback without previously registering"
+ + " any.";
return;
}
Long ptr = mUserActionTestingCallbackNativePtrs.remove(callback);
if (ptr == null) {
- assert false : "Attempting to remove a user action callback that was never previously"
- + " registered.";
+ assert false
+ : "Attempting to remove a user action callback that was never previously"
+ + " registered.";
return;
}
NativeUmaRecorderJni.get().removeActionCallbackForTesting(ptr);
@@ -139,10 +144,13 @@
@NativeMethods
public interface Natives {
long recordBooleanHistogram(String name, long nativeHint, boolean sample);
+
long recordExponentialHistogram(
String name, long nativeHint, int sample, int min, int max, int numBuckets);
+
long recordLinearHistogram(
String name, long nativeHint, int sample, int min, int max, int numBuckets);
+
long recordSparseHistogram(String name, long nativeHint, int sample);
/**
@@ -157,13 +165,17 @@
void recordUserAction(String name, long millisSinceEvent);
int getHistogramValueCountForTesting(String name, int sample, long snapshotPtr);
+
int getHistogramTotalCountForTesting(String name, long snapshotPtr);
+
long[] getHistogramSamplesForTesting(String name);
long createHistogramSnapshotForTesting();
+
void destroyHistogramSnapshotForTesting(long snapshotPtr);
long addActionCallbackForTesting(Callback<String> callback);
+
void removeActionCallbackForTesting(long callbackId);
}
}
diff --git a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
index 6cb80f7..2c839a4 100644
--- a/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
+++ b/base/android/java/src/org/chromium/base/metrics/RecordHistogram.java
@@ -262,8 +262,9 @@
private static void recordCustomTimesHistogramMilliseconds(
String name, long duration, long min, long max, int numBuckets) {
- UmaRecorderHolder.get().recordExponentialHistogram(
- name, clampToInt(duration), clampToInt(min), clampToInt(max), numBuckets);
+ UmaRecorderHolder.get()
+ .recordExponentialHistogram(
+ name, clampToInt(duration), clampToInt(min), clampToInt(max), numBuckets);
}
/**
diff --git a/base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java b/base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java
index 7b88da8..5089bd2 100644
--- a/base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java
+++ b/base/android/java/src/org/chromium/base/metrics/ScopedSysTraceEvent.java
@@ -28,9 +28,7 @@
return new ScopedSysTraceEvent(name);
}
- /**
- * Constructor used to support the "try with resource" construct.
- */
+ /** Constructor used to support the "try with resource" construct. */
private ScopedSysTraceEvent(String name) {
Trace.beginSection(name);
}
@@ -39,4 +37,4 @@
public void close() {
Trace.endSection();
}
-}
\ No newline at end of file
+}
diff --git a/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java b/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java
index 63f936c..e2461a2 100644
--- a/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java
+++ b/base/android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java
@@ -28,4 +28,4 @@
interface Natives {
String toJson(@JSONVerbosityLevel int verbosityLevel);
}
-}
\ No newline at end of file
+}
diff --git a/base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java b/base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java
index 1ea607a..b938fbe 100644
--- a/base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java
+++ b/base/android/java/src/org/chromium/base/metrics/UmaRecorderHolder.java
@@ -34,7 +34,7 @@
public static void setNonNativeDelegate(UmaRecorder recorder) {
UmaRecorder previous = sRecorder.setDelegate(recorder);
assert !(previous instanceof NativeUmaRecorder)
- : "A NativeUmaRecorder has already been set";
+ : "A NativeUmaRecorder has already been set";
}
/**
@@ -46,9 +46,7 @@
sSetUpNativeUmaRecorder = setUpNativeUmaRecorder;
}
- /**
- * Starts forwarding metrics to the native code. Returns after the cache has been flushed.
- */
+ /** Starts forwarding metrics to the native code. Returns after the cache has been flushed. */
public static void onLibraryLoaded() {
if (!sSetUpNativeUmaRecorder) return;
@@ -57,9 +55,7 @@
sRecorder.setDelegate(new NativeUmaRecorder());
}
- /**
- * Reset globals for tests.
- */
+ /** Reset globals for tests. */
public static void resetForTesting() {
// Prevent hitting cache size limits from tests running without ever switching to the native
// recorder. Also guards against tests that use setNonNativeDelegate() to inject a mock from
diff --git a/base/android/java/src/org/chromium/base/process_launcher/BindService.java b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
index 16deaed..0ada30f 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/BindService.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/BindService.java
@@ -22,9 +22,7 @@
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
-/**
- * Class of static helper methods to call Context.bindService variants.
- */
+/** Class of static helper methods to call Context.bindService variants. */
final class BindService {
private static Method sBindServiceAsUserMethod;
@@ -35,8 +33,14 @@
// Note that handler is not guaranteed to be used, and client still need to correctly handle
// callbacks on the UI thread.
- static boolean doBindService(Context context, Intent intent, ServiceConnection connection,
- int flags, Handler handler, Executor executor, String instanceName) {
+ static boolean doBindService(
+ Context context,
+ Intent intent,
+ ServiceConnection connection,
+ int flags,
+ Handler handler,
+ Executor executor,
+ String instanceName) {
if (supportVariableConnections() && instanceName != null) {
return ApiHelperForQ.bindIsolatedService(
context, intent, flags, instanceName, executor, connection);
@@ -65,21 +69,31 @@
@RequiresApi(Build.VERSION_CODES.N)
@SuppressLint("DiscouragedPrivateApi")
- private static boolean bindServiceByReflection(Context context, Intent intent,
- ServiceConnection connection, int flags, Handler handler)
+ private static boolean bindServiceByReflection(
+ Context context,
+ Intent intent,
+ ServiceConnection connection,
+ int flags,
+ Handler handler)
throws ReflectiveOperationException {
if (sBindServiceAsUserMethod == null) {
sBindServiceAsUserMethod =
- Context.class.getDeclaredMethod("bindServiceAsUser", Intent.class,
- ServiceConnection.class, int.class, Handler.class, UserHandle.class);
+ Context.class.getDeclaredMethod(
+ "bindServiceAsUser",
+ Intent.class,
+ ServiceConnection.class,
+ int.class,
+ Handler.class,
+ UserHandle.class);
}
// No need for null checks or worry about infinite looping here. Otherwise a regular calls
// into the ContextWrapper would lead to problems as well.
while (context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
- return (Boolean) sBindServiceAsUserMethod.invoke(
- context, intent, connection, flags, handler, Process.myUserHandle());
+ return (Boolean)
+ sBindServiceAsUserMethod.invoke(
+ context, intent, connection, flags, handler, Process.myUserHandle());
}
private BindService() {}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java b/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
index b9f6567..1b1cce1 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java
@@ -43,19 +43,35 @@
/** Factory interface. Used by tests to specialize created connections. */
@VisibleForTesting
public interface ConnectionFactory {
- ChildProcessConnection createConnection(Context context, ComponentName serviceName,
- ComponentName fallbackServiceName, boolean bindToCaller,
- boolean bindAsExternalService, Bundle serviceBundle, String instanceName);
+ ChildProcessConnection createConnection(
+ Context context,
+ ComponentName serviceName,
+ ComponentName fallbackServiceName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ Bundle serviceBundle,
+ String instanceName);
}
/** Default implementation of the ConnectionFactory that creates actual connections. */
private static class ConnectionFactoryImpl implements ConnectionFactory {
@Override
- public ChildProcessConnection createConnection(Context context, ComponentName serviceName,
- ComponentName fallbackServiceName, boolean bindToCaller,
- boolean bindAsExternalService, Bundle serviceBundle, String instanceName) {
- return new ChildProcessConnection(context, serviceName, fallbackServiceName,
- bindToCaller, bindAsExternalService, serviceBundle, instanceName);
+ public ChildProcessConnection createConnection(
+ Context context,
+ ComponentName serviceName,
+ ComponentName fallbackServiceName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ Bundle serviceBundle,
+ String instanceName) {
+ return new ChildProcessConnection(
+ context,
+ serviceName,
+ fallbackServiceName,
+ bindToCaller,
+ bindAsExternalService,
+ serviceBundle,
+ instanceName);
}
}
@@ -124,9 +140,15 @@
* Factory method that retrieves the service name and number of service from the
* AndroidManifest.xml.
*/
- public static ChildConnectionAllocator create(Context context, Handler launcherHandler,
- Runnable freeSlotCallback, String packageName, String serviceClassName,
- String numChildServicesManifestKey, boolean bindToCaller, boolean bindAsExternalService,
+ public static ChildConnectionAllocator create(
+ Context context,
+ Handler launcherHandler,
+ Runnable freeSlotCallback,
+ String packageName,
+ String serviceClassName,
+ String numChildServicesManifestKey,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
boolean useStrongBinding) {
int numServices = -1;
PackageManager packageManager = context.getPackageManager();
@@ -146,31 +168,50 @@
checkServiceExists(context, packageName, serviceClassName);
- return new FixedSizeAllocatorImpl(launcherHandler, freeSlotCallback, packageName,
- serviceClassName, bindToCaller, bindAsExternalService, useStrongBinding,
+ return new FixedSizeAllocatorImpl(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding,
numServices);
}
- public static ChildConnectionAllocator createVariableSize(Context context,
- Handler launcherHandler, Runnable freeSlotCallback, String packageName,
- String serviceClassName, boolean bindToCaller, boolean bindAsExternalService,
+ public static ChildConnectionAllocator createVariableSize(
+ Context context,
+ Handler launcherHandler,
+ Runnable freeSlotCallback,
+ String packageName,
+ String serviceClassName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
boolean useStrongBinding) {
checkServiceExists(context, packageName, serviceClassName);
// OnePlus devices are having trouble with app zygote in combination with dynamic
// feature modules. See crbug.com/1064314 for details.
BuildInfo buildInfo = BuildInfo.getInstance();
- boolean disableZygote = Build.VERSION.SDK_INT == 29
- && buildInfo.androidBuildFingerprint.startsWith("OnePlus/");
+ boolean disableZygote =
+ Build.VERSION.SDK_INT == 29
+ && buildInfo.androidBuildFingerprint.startsWith("OnePlus/");
if (Build.VERSION.SDK_INT == 29 && !disableZygote) {
UserManager userManager =
- (UserManager) ContextUtils.getApplicationContext().getSystemService(
- Context.USER_SERVICE);
+ (UserManager)
+ ContextUtils.getApplicationContext()
+ .getSystemService(Context.USER_SERVICE);
if (!ApiHelperForM.isSystemUser(userManager)) {
- return new Android10WorkaroundAllocatorImpl(launcherHandler, freeSlotCallback,
- packageName, serviceClassName, bindToCaller, bindAsExternalService,
- useStrongBinding, MAX_VARIABLE_ALLOCATED);
+ return new Android10WorkaroundAllocatorImpl(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding,
+ MAX_VARIABLE_ALLOCATED);
}
}
// On low end devices, we do not expect to have many renderers. As a consequence, the fixed
@@ -180,44 +221,91 @@
String suffix = disableZygote ? NON_ZYGOTE_SUFFIX : ZYGOTE_SUFFIX;
String fallbackServiceClassName =
disableZygote ? null : serviceClassName + NON_ZYGOTE_SUFFIX;
- return new VariableSizeAllocatorImpl(launcherHandler, freeSlotCallback, packageName,
- serviceClassName + suffix, fallbackServiceClassName, bindToCaller,
- bindAsExternalService, useStrongBinding, MAX_VARIABLE_ALLOCATED);
+ return new VariableSizeAllocatorImpl(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName + suffix,
+ fallbackServiceClassName,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding,
+ MAX_VARIABLE_ALLOCATED);
}
/**
* Factory method used with some tests to create an allocator with values passed in directly
* instead of being retrieved from the AndroidManifest.xml.
*/
- public static FixedSizeAllocatorImpl createFixedForTesting(Runnable freeSlotCallback,
- String packageName, String serviceClassName, int serviceCount, boolean bindToCaller,
- boolean bindAsExternalService, boolean useStrongBinding) {
- return new FixedSizeAllocatorImpl(new Handler(), freeSlotCallback, packageName,
- serviceClassName, bindToCaller, bindAsExternalService, useStrongBinding,
+ public static FixedSizeAllocatorImpl createFixedForTesting(
+ Runnable freeSlotCallback,
+ String packageName,
+ String serviceClassName,
+ int serviceCount,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ boolean useStrongBinding) {
+ return new FixedSizeAllocatorImpl(
+ new Handler(),
+ freeSlotCallback,
+ packageName,
+ serviceClassName,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding,
serviceCount);
}
- public static VariableSizeAllocatorImpl createVariableSizeForTesting(Handler launcherHandler,
- String packageName, Runnable freeSlotCallback, String serviceClassName,
- boolean bindToCaller, boolean bindAsExternalService, boolean useStrongBinding,
+ public static VariableSizeAllocatorImpl createVariableSizeForTesting(
+ Handler launcherHandler,
+ String packageName,
+ Runnable freeSlotCallback,
+ String serviceClassName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ boolean useStrongBinding,
int maxAllocated) {
- return new VariableSizeAllocatorImpl(launcherHandler, freeSlotCallback, packageName,
- serviceClassName + ZYGOTE_SUFFIX, null, bindToCaller, bindAsExternalService,
- useStrongBinding, maxAllocated);
- }
-
- public static Android10WorkaroundAllocatorImpl createWorkaroundForTesting(
- Handler launcherHandler, String packageName, Runnable freeSlotCallback,
- String serviceClassName, boolean bindToCaller, boolean bindAsExternalService,
- boolean useStrongBinding, int maxAllocated) {
- return new Android10WorkaroundAllocatorImpl(launcherHandler, freeSlotCallback, packageName,
- serviceClassName, bindToCaller, bindAsExternalService, useStrongBinding,
+ return new VariableSizeAllocatorImpl(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName + ZYGOTE_SUFFIX,
+ null,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding,
maxAllocated);
}
- private ChildConnectionAllocator(Handler launcherHandler, Runnable freeSlotCallback,
- String packageName, String serviceClassName, String fallbackServiceClassName,
- boolean bindToCaller, boolean bindAsExternalService, boolean useStrongBinding) {
+ public static Android10WorkaroundAllocatorImpl createWorkaroundForTesting(
+ Handler launcherHandler,
+ String packageName,
+ Runnable freeSlotCallback,
+ String serviceClassName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ boolean useStrongBinding,
+ int maxAllocated) {
+ return new Android10WorkaroundAllocatorImpl(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding,
+ maxAllocated);
+ }
+
+ private ChildConnectionAllocator(
+ Handler launcherHandler,
+ Runnable freeSlotCallback,
+ String packageName,
+ String serviceClassName,
+ String fallbackServiceClassName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ boolean useStrongBinding) {
mLauncherHandler = launcherHandler;
assert isRunningOnLauncherThread();
mFreeSlotCallback = freeSlotCallback;
@@ -229,8 +317,12 @@
mUseStrongBinding = useStrongBinding;
}
- /** @return a bound connection, or null if there are no free slots. */
- public ChildProcessConnection allocate(Context context, Bundle serviceBundle,
+ /**
+ * @return a bound connection, or null if there are no free slots.
+ */
+ public ChildProcessConnection allocate(
+ Context context,
+ Bundle serviceBundle,
final ChildProcessConnection.ServiceCallback serviceCallback) {
assert isRunningOnLauncherThread();
@@ -245,12 +337,13 @@
public void onChildStarted() {
assert isRunningOnLauncherThread();
if (serviceCallback != null) {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- serviceCallback.onChildStarted();
- }
- });
+ mLauncherHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ serviceCallback.onChildStarted();
+ }
+ });
}
}
@@ -258,12 +351,13 @@
public void onChildStartFailed(final ChildProcessConnection connection) {
assert isRunningOnLauncherThread();
if (serviceCallback != null) {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- serviceCallback.onChildStartFailed(connection);
- }
- });
+ mLauncherHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ serviceCallback.onChildStartFailed(connection);
+ }
+ });
}
freeConnectionWithDelay(connection);
}
@@ -272,12 +366,13 @@
public void onChildProcessDied(final ChildProcessConnection connection) {
assert isRunningOnLauncherThread();
if (serviceCallback != null) {
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- serviceCallback.onChildProcessDied(connection);
- }
- });
+ mLauncherHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ serviceCallback.onChildProcessDied(connection);
+ }
+ });
}
freeConnectionWithDelay(connection);
}
@@ -289,12 +384,14 @@
// time. If a new connection to the same service is bound at that point, the
// process is reused and bad things happen (mostly static variables are set
// when we don't expect them to).
- mLauncherHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- free(connection);
- }
- }, FREE_CONNECTION_DELAY_MILLIS);
+ mLauncherHandler.postDelayed(
+ new Runnable() {
+ @Override
+ public void run() {
+ free(connection);
+ }
+ },
+ FREE_CONNECTION_DELAY_MILLIS);
}
};
@@ -339,8 +436,11 @@
return mLauncherHandler.getLooper() == Looper.myLooper();
}
- /* package */ abstract ChildProcessConnection doAllocate(Context context, Bundle serviceBundle,
+ /* package */ abstract ChildProcessConnection doAllocate(
+ Context context,
+ Bundle serviceBundle,
ChildProcessConnection.ServiceCallback serviceCallback);
+
/* package */ abstract void doFree(ChildProcessConnection connection);
/** Implementation class accessed directly by tests. */
@@ -352,11 +452,24 @@
// The list of free (not bound) service indices.
private final ArrayList<Integer> mFreeConnectionIndices;
- private FixedSizeAllocatorImpl(Handler launcherHandler, Runnable freeSlotCallback,
- String packageName, String serviceClassName, boolean bindToCaller,
- boolean bindAsExternalService, boolean useStrongBinding, int numChildServices) {
- super(launcherHandler, freeSlotCallback, packageName, serviceClassName, null,
- bindToCaller, bindAsExternalService, useStrongBinding);
+ private FixedSizeAllocatorImpl(
+ Handler launcherHandler,
+ Runnable freeSlotCallback,
+ String packageName,
+ String serviceClassName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ boolean useStrongBinding,
+ int numChildServices) {
+ super(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName,
+ null,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding);
mChildProcessConnections = new ChildProcessConnection[numChildServices];
@@ -367,7 +480,9 @@
}
@Override
- /* package */ ChildProcessConnection doAllocate(Context context, Bundle serviceBundle,
+ /* package */ ChildProcessConnection doAllocate(
+ Context context,
+ Bundle serviceBundle,
ChildProcessConnection.ServiceCallback serviceCallback) {
if (mFreeConnectionIndices.isEmpty()) {
Log.w(TAG, "Ran out of services to allocate.");
@@ -378,12 +493,21 @@
ComponentName serviceName = new ComponentName(mPackageName, mServiceClassName + slot);
ComponentName fallbackServiceName = null;
- ChildProcessConnection connection = mConnectionFactory.createConnection(context,
- serviceName, fallbackServiceName, mBindToCaller, mBindAsExternalService,
- serviceBundle, null /* instanceName */);
+ ChildProcessConnection connection =
+ mConnectionFactory.createConnection(
+ context,
+ serviceName,
+ fallbackServiceName,
+ mBindToCaller,
+ mBindAsExternalService,
+ serviceBundle,
+ /* instanceName= */ null);
mChildProcessConnections[slot] = connection;
- Log.d(TAG, "Allocator allocated and bound a connection, name: %s, slot: %d",
- mServiceClassName, slot);
+ Log.d(
+ TAG,
+ "Allocator allocated and bound a connection, name: %s, slot: %d",
+ mServiceClassName,
+ slot);
connection.start(mUseStrongBinding, serviceCallback);
return connection;
}
@@ -400,7 +524,10 @@
mChildProcessConnections[slot] = null;
assert !mFreeConnectionIndices.contains(slot);
mFreeConnectionIndices.add(slot);
- Log.d(TAG, "Allocator freed a connection, name: %s, slot: %d", mServiceClassName,
+ Log.d(
+ TAG,
+ "Allocator freed a connection, name: %s, slot: %d",
+ mServiceClassName,
slot);
}
}
@@ -437,19 +564,33 @@
private int mNextInstance;
// Note |serviceClassName| includes the service suffix.
- private VariableSizeAllocatorImpl(Handler launcherHandler, Runnable freeSlotCallback,
- String packageName, String serviceClassName, String fallbackServiceClassName,
- boolean bindToCaller, boolean bindAsExternalService, boolean useStrongBinding,
+ private VariableSizeAllocatorImpl(
+ Handler launcherHandler,
+ Runnable freeSlotCallback,
+ String packageName,
+ String serviceClassName,
+ String fallbackServiceClassName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ boolean useStrongBinding,
int maxAllocated) {
- super(launcherHandler, freeSlotCallback, packageName, serviceClassName,
- fallbackServiceClassName, bindToCaller, bindAsExternalService,
+ super(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName,
+ fallbackServiceClassName,
+ bindToCaller,
+ bindAsExternalService,
useStrongBinding);
assert maxAllocated > 0;
mMaxAllocated = maxAllocated;
}
@Override
- /* package */ ChildProcessConnection doAllocate(Context context, Bundle serviceBundle,
+ /* package */ ChildProcessConnection doAllocate(
+ Context context,
+ Bundle serviceBundle,
ChildProcessConnection.ServiceCallback serviceCallback) {
ChildProcessConnection connection = allocate(context, serviceBundle);
if (connection == null) return null;
@@ -458,7 +599,9 @@
return connection;
}
- /* package */ ChildProcessConnection tryAllocate(Context context, Bundle serviceBundle,
+ /* package */ ChildProcessConnection tryAllocate(
+ Context context,
+ Bundle serviceBundle,
ChildProcessConnection.ServiceCallback serviceCallback) {
ChildProcessConnection connection = allocate(context, serviceBundle);
if (connection == null) return null;
@@ -481,8 +624,14 @@
String instanceName = Integer.toString(mNextInstance);
mNextInstance++;
ChildProcessConnection connection =
- mConnectionFactory.createConnection(context, serviceName, fallbackServiceName,
- mBindToCaller, mBindAsExternalService, serviceBundle, instanceName);
+ mConnectionFactory.createConnection(
+ context,
+ serviceName,
+ fallbackServiceName,
+ mBindToCaller,
+ mBindAsExternalService,
+ serviceBundle,
+ instanceName);
assert connection != null;
return connection;
}
@@ -527,21 +676,52 @@
private final VariableSizeAllocatorImpl mZygoteAllocator;
private final VariableSizeAllocatorImpl mNonZygoteAllocator;
- private Android10WorkaroundAllocatorImpl(Handler launcherHandler, Runnable freeSlotCallback,
- String packageName, String serviceClassName, boolean bindToCaller,
- boolean bindAsExternalService, boolean useStrongBinding, int maxAllocated) {
- super(launcherHandler, freeSlotCallback, packageName, serviceClassName, null,
- bindToCaller, bindAsExternalService, useStrongBinding);
- mZygoteAllocator = new VariableSizeAllocatorImpl(launcherHandler, freeSlotCallback,
- packageName, serviceClassName + ZYGOTE_SUFFIX, null, bindToCaller,
- bindAsExternalService, useStrongBinding, maxAllocated);
- mNonZygoteAllocator = new VariableSizeAllocatorImpl(launcherHandler, freeSlotCallback,
- packageName, serviceClassName + NON_ZYGOTE_SUFFIX, null, bindToCaller,
- bindAsExternalService, useStrongBinding, maxAllocated);
+ private Android10WorkaroundAllocatorImpl(
+ Handler launcherHandler,
+ Runnable freeSlotCallback,
+ String packageName,
+ String serviceClassName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ boolean useStrongBinding,
+ int maxAllocated) {
+ super(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName,
+ null,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding);
+ mZygoteAllocator =
+ new VariableSizeAllocatorImpl(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName + ZYGOTE_SUFFIX,
+ null,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding,
+ maxAllocated);
+ mNonZygoteAllocator =
+ new VariableSizeAllocatorImpl(
+ launcherHandler,
+ freeSlotCallback,
+ packageName,
+ serviceClassName + NON_ZYGOTE_SUFFIX,
+ null,
+ bindToCaller,
+ bindAsExternalService,
+ useStrongBinding,
+ maxAllocated);
}
@Override
- /* package */ ChildProcessConnection doAllocate(Context context, Bundle serviceBundle,
+ /* package */ ChildProcessConnection doAllocate(
+ Context context,
+ Bundle serviceBundle,
ChildProcessConnection.ServiceCallback serviceCallback) {
ChildProcessConnection connection =
mZygoteAllocator.tryAllocate(context, serviceBundle, serviceCallback);
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
index 47543e3..553ed6a 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java
@@ -16,12 +16,9 @@
import android.os.Looper;
import android.os.RemoteException;
-import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import org.chromium.base.BaseFeatureMap;
-import org.chromium.base.BaseFeatures;
import org.chromium.base.BuildInfo;
import org.chromium.base.ChildBindingState;
import org.chromium.base.Log;
@@ -34,8 +31,6 @@
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.build.BuildConfig;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -43,9 +38,7 @@
import javax.annotation.concurrent.GuardedBy;
-/**
- * Manages a connection between the browser activity and a child service.
- */
+/** Manages a connection between the browser activity and a child service. */
public class ChildProcessConnection {
private static final String TAG = "ChildProcessConn";
private static final int FALLBACK_TIMEOUT_IN_SECONDS = 10;
@@ -78,9 +71,7 @@
void onChildProcessDied(ChildProcessConnection connection);
}
- /**
- * Used to notify the consumer about the connection being established.
- */
+ /** Used to notify the consumer about the connection being established. */
public interface ConnectionCallback {
/**
* Called when the connection to the service is established.
@@ -114,23 +105,17 @@
}
}
- /**
- * Run time check if variable number of connections is supported.
- */
+ /** Run time check if variable number of connections is supported. */
public static boolean supportVariableConnections() {
return BindService.supportVariableConnections();
}
- /**
- * Run time check if not perceptible binding is supported.
- */
+ /** Run time check if not perceptible binding is supported. */
public static boolean supportNotPerceptibleBinding() {
return SUPPORT_NOT_PERCEPTIBLE_BINDING;
}
- /**
- * The string passed to bindToCaller to identify this class loader.
- */
+ /** The string passed to bindToCaller to identify this class loader. */
@VisibleForTesting
public static String getBindToCallerClazz() {
// TODO(crbug.com/1057102): Have embedder explicitly set separate different strings since
@@ -284,28 +269,47 @@
@GuardedBy("mBindingStateLock")
private boolean mCleanExit;
- public ChildProcessConnection(Context context, ComponentName serviceName,
- ComponentName fallbackServiceName, boolean bindToCaller, boolean bindAsExternalService,
- Bundle serviceBundle, String instanceName) {
- this(context, serviceName, fallbackServiceName, bindToCaller, bindAsExternalService,
- serviceBundle, null /* connectionFactory */, instanceName);
+ public ChildProcessConnection(
+ Context context,
+ ComponentName serviceName,
+ ComponentName fallbackServiceName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ Bundle serviceBundle,
+ String instanceName) {
+ this(
+ context,
+ serviceName,
+ fallbackServiceName,
+ bindToCaller,
+ bindAsExternalService,
+ serviceBundle,
+ /* connectionFactory= */ null,
+ instanceName);
}
@VisibleForTesting
- public ChildProcessConnection(final Context context, ComponentName serviceName,
- ComponentName fallbackServiceName, boolean bindToCaller, boolean bindAsExternalService,
- Bundle serviceBundle, ChildServiceConnectionFactory connectionFactory,
+ public ChildProcessConnection(
+ final Context context,
+ ComponentName serviceName,
+ ComponentName fallbackServiceName,
+ boolean bindToCaller,
+ boolean bindAsExternalService,
+ Bundle serviceBundle,
+ ChildServiceConnectionFactory connectionFactory,
String instanceName) {
mLauncherHandler = new Handler();
- mLauncherExecutor = (Runnable runnable) -> {
- mLauncherHandler.post(runnable);
- };
+ mLauncherExecutor =
+ (Runnable runnable) -> {
+ mLauncherHandler.post(runnable);
+ };
assert isRunningOnLauncherThread();
mServiceName = serviceName;
mFallbackServiceName = fallbackServiceName;
mServiceBundle = serviceBundle != null ? serviceBundle : new Bundle();
mServiceBundle.putBoolean(ChildProcessConstants.EXTRA_BIND_TO_CALLER, bindToCaller);
- mServiceBundle.putString(ChildProcessConstants.EXTRA_BROWSER_PACKAGE_NAME,
+ mServiceBundle.putString(
+ ChildProcessConstants.EXTRA_BROWSER_PACKAGE_NAME,
BuildInfo.getInstance().packageName);
mBindToCaller = bindToCaller;
mInstanceName = instanceName;
@@ -313,42 +317,55 @@
// isolatedProcess, so both need to be turned off for incremental install.
mBindAsExternalService = bindAsExternalService && !BuildConfig.IS_INCREMENTAL_INSTALL;
if (connectionFactory == null) {
- mConnectionFactory = new ChildServiceConnectionFactory() {
- @Override
- public ChildServiceConnection createConnection(Intent bindIntent, int bindFlags,
- ChildServiceConnectionDelegate delegate, String instanceName) {
- return new ChildServiceConnectionImpl(context, bindIntent, bindFlags,
- mLauncherHandler, mLauncherExecutor, delegate, instanceName);
- }
- };
+ mConnectionFactory =
+ new ChildServiceConnectionFactory() {
+ @Override
+ public ChildServiceConnection createConnection(
+ Intent bindIntent,
+ int bindFlags,
+ ChildServiceConnectionDelegate delegate,
+ String instanceName) {
+ return new ChildServiceConnectionImpl(
+ context,
+ bindIntent,
+ bindFlags,
+ mLauncherHandler,
+ mLauncherExecutor,
+ delegate,
+ instanceName);
+ }
+ };
} else {
mConnectionFactory = connectionFactory;
}
// Methods on the delegate are can be called on launcher thread or UI thread, so need to
// handle both cases. See BindService for details.
- mConnectionDelegate = new ChildServiceConnectionDelegate() {
- @Override
- public void onServiceConnected(final IBinder service) {
- if (mLauncherHandler.getLooper() == Looper.myLooper()) {
- onServiceConnectedOnLauncherThread(service);
- return;
- }
- mLauncherHandler.post(() -> onServiceConnectedOnLauncherThread(service));
- }
+ mConnectionDelegate =
+ new ChildServiceConnectionDelegate() {
+ @Override
+ public void onServiceConnected(final IBinder service) {
+ if (mLauncherHandler.getLooper() == Looper.myLooper()) {
+ onServiceConnectedOnLauncherThread(service);
+ return;
+ }
+ mLauncherHandler.post(() -> onServiceConnectedOnLauncherThread(service));
+ }
- @Override
- public void onServiceDisconnected() {
- if (mLauncherHandler.getLooper() == Looper.myLooper()) {
- onServiceDisconnectedOnLauncherThread();
- return;
- }
- mLauncherHandler.post(() -> onServiceDisconnectedOnLauncherThread());
- }
- };
+ @Override
+ public void onServiceDisconnected() {
+ if (mLauncherHandler.getLooper() == Looper.myLooper()) {
+ onServiceDisconnectedOnLauncherThread();
+ return;
+ }
+ mLauncherHandler.post(() -> onServiceDisconnectedOnLauncherThread());
+ }
+ };
- createBindings(sAlwaysFallback && mFallbackServiceName != null ? mFallbackServiceName
- : mServiceName);
+ createBindings(
+ sAlwaysFallback && mFallbackServiceName != null
+ ? mFallbackServiceName
+ : mServiceName);
}
private void createBindings(ComponentName serviceName) {
@@ -358,21 +375,34 @@
intent.putExtras(mServiceBundle);
}
- int defaultFlags = Context.BIND_AUTO_CREATE
- | (mBindAsExternalService ? Context.BIND_EXTERNAL_SERVICE : 0);
+ int defaultFlags =
+ Context.BIND_AUTO_CREATE
+ | (mBindAsExternalService ? Context.BIND_EXTERNAL_SERVICE : 0);
- mVisibleBinding = mConnectionFactory.createConnection(
- intent, defaultFlags, mConnectionDelegate, mInstanceName);
+ mVisibleBinding =
+ mConnectionFactory.createConnection(
+ intent, defaultFlags, mConnectionDelegate, mInstanceName);
if (supportNotPerceptibleBinding()) {
- mNotPerceptibleBinding = mConnectionFactory.createConnection(intent,
- defaultFlags | Context.BIND_NOT_PERCEPTIBLE, mConnectionDelegate,
- mInstanceName);
+ mNotPerceptibleBinding =
+ mConnectionFactory.createConnection(
+ intent,
+ defaultFlags | Context.BIND_NOT_PERCEPTIBLE,
+ mConnectionDelegate,
+ mInstanceName);
}
- mStrongBinding = mConnectionFactory.createConnection(
- intent, defaultFlags | Context.BIND_IMPORTANT, mConnectionDelegate, mInstanceName);
- mWaivedBinding = mConnectionFactory.createConnection(intent,
- defaultFlags | Context.BIND_WAIVE_PRIORITY, mConnectionDelegate, mInstanceName);
+ mStrongBinding =
+ mConnectionFactory.createConnection(
+ intent,
+ defaultFlags | Context.BIND_IMPORTANT,
+ mConnectionDelegate,
+ mInstanceName);
+ mWaivedBinding =
+ mConnectionFactory.createConnection(
+ intent,
+ defaultFlags | Context.BIND_WAIVE_PRIORITY,
+ mConnectionDelegate,
+ mInstanceName);
}
public final IChildProcessService getService() {
@@ -419,8 +449,8 @@
try {
TraceEvent.begin("ChildProcessConnection.start");
assert isRunningOnLauncherThread();
- assert mConnectionParams
- == null : "setupConnection() called before start() in ChildProcessConnection.";
+ assert mConnectionParams == null
+ : "setupConnection() called before start() in ChildProcessConnection.";
mServiceCallback = serviceCallback;
@@ -443,8 +473,8 @@
try {
TraceEvent.begin("ChildProcessConnection.tryStart");
assert isRunningOnLauncherThread();
- assert mConnectionParams
- == null : "setupConnection() called before start() in ChildProcessConnection.";
+ assert mConnectionParams == null
+ : "setupConnection() called before start() in ChildProcessConnection.";
if (!bind(useStrongBinding)) {
return false;
@@ -469,16 +499,20 @@
/**
* Sets-up the connection after it was started with start().
+ *
* @param connectionBundle a bundle passed to the service that can be used to pass various
- * parameters to the service
+ * parameters to the service
* @param clientInterfaces optional client specified interfaces that the child can use to
- * communicate with the parent process
+ * communicate with the parent process
* @param connectionCallback will be called exactly once after the connection is set up or the
- * setup fails
+ * setup fails
* @param zygoteInfoCallback will be called exactly once after the connection is set up
*/
- public void setupConnection(Bundle connectionBundle, @Nullable List<IBinder> clientInterfaces,
- ConnectionCallback connectionCallback, ZygoteInfoCallback zygoteInfoCallback) {
+ public void setupConnection(
+ Bundle connectionBundle,
+ @Nullable List<IBinder> clientInterfaces,
+ ConnectionCallback connectionCallback,
+ ZygoteInfoCallback zygoteInfoCallback) {
assert isRunningOnLauncherThread();
assert mConnectionParams == null;
if (mServiceDisconnected) {
@@ -523,9 +557,7 @@
notifyChildProcessDied();
}
- /**
- * Dumps the stack of the child process without crashing it.
- */
+ /** Dumps the stack of the child process without crashing it. */
public void dumpProcessStack() {
assert isRunningOnLauncherThread();
IChildProcessService service = mService;
@@ -536,28 +568,6 @@
}
}
- /**
- * UMA histogram values for child app info mismatches.
- * Note: this should stay in sync with ChildAppInfoError in enums.xml.
- */
- @IntDef({ChildAppInfoError.SUCCESS, ChildAppInfoError.SOURCE_DIR_MISMATCH,
- ChildAppInfoError.SHARED_LIB_MISMATCH, ChildAppInfoError.REMOTE_EXCEPTION,
- ChildAppInfoError.MAX_VALUE})
- @Retention(RetentionPolicy.SOURCE)
- public @interface ChildAppInfoError {
- int SUCCESS = 0;
- int SOURCE_DIR_MISMATCH = 1;
- int SHARED_LIB_MISMATCH = 2;
- int REMOTE_EXCEPTION = 3;
- // New elements go above.
- int MAX_VALUE = REMOTE_EXCEPTION;
- }
-
- private void recordChildAppInfoError(@ChildAppInfoError int error) {
- RecordHistogram.recordEnumeratedHistogram(
- "Android.ChildMismatch.AppInfoError2", error, ChildAppInfoError.MAX_VALUE);
- }
-
@VisibleForTesting
protected void onServiceConnectedOnLauncherThread(IBinder service) {
assert isRunningOnLauncherThread();
@@ -589,46 +599,42 @@
}
// Validate that the child process is running the same code as the parent process.
- String childMismatchError = null;
+ boolean childMatches;
try {
ApplicationInfo child = mService.getAppInfo();
ApplicationInfo parent = BuildInfo.getInstance().getBrowserApplicationInfo();
-
- if (!Objects.equals(parent.sourceDir, child.sourceDir)) {
- recordChildAppInfoError(ChildAppInfoError.SOURCE_DIR_MISMATCH);
- childMismatchError = "sourceDir mismatch; parent=" + parent.sourceDir
- + " child=" + child.sourceDir;
- } else if (!Arrays.equals(parent.sharedLibraryFiles, child.sharedLibraryFiles)) {
- recordChildAppInfoError(ChildAppInfoError.SHARED_LIB_MISMATCH);
- childMismatchError = "sharedLibraryFiles mismatch; parent="
- + Arrays.toString(parent.sharedLibraryFiles)
- + " child=" + Arrays.toString(child.sharedLibraryFiles);
- }
// Don't compare splitSourceDirs as isolatedSplits/dynamic feature modules/etc make
// this potentially complicated.
+ childMatches =
+ Objects.equals(parent.sourceDir, child.sourceDir)
+ && Arrays.equals(
+ parent.sharedLibraryFiles, child.sharedLibraryFiles);
} catch (RemoteException ex) {
- recordChildAppInfoError(ChildAppInfoError.REMOTE_EXCEPTION);
- childMismatchError = "child didn't handle getAppInfo()";
+ // If the child can't handle getAppInfo then it is old and doesn't match.
+ childMatches = false;
}
- if (childMismatchError != null) {
+ if (!childMatches) {
// Check if it looks like the browser's package version has been changed since the
// browser process launched (i.e. if the install somehow did not kill our process)
PackageInfo latestPackage = PackageUtils.getApplicationPackageInfo(0);
long latestVersionCode = BuildInfo.packageVersionCode(latestPackage);
long loadedVersionCode = BuildInfo.getInstance().versionCode;
- boolean versionHasChanged = latestVersionCode != loadedVersionCode;
- RecordHistogram.recordBooleanHistogram(
- "Android.ChildMismatch.BrowserVersionChanged2", versionHasChanged);
- childMismatchError += "; browser version has changed: " + versionHasChanged;
- Log.e(TAG, "Child process code mismatch: %s", childMismatchError);
- boolean crashIfBrowserChanged = BaseFeatureMap.isEnabled(
- BaseFeatures.CRASH_BROWSER_ON_CHILD_MISMATCH_IF_BROWSER_CHANGED);
- if (BaseFeatureMap.isEnabled(BaseFeatures.CRASH_BROWSER_ON_ANY_CHILD_MISMATCH)
- || (versionHasChanged && crashIfBrowserChanged)) {
- throw new ChildProcessMismatchException(childMismatchError);
+ if (latestVersionCode != loadedVersionCode) {
+ // Crashing the process is likely to improve the situation - when we are next
+ // launched, we should be running the new version and match new children.
+ throw new ChildProcessMismatchException(
+ "Child process's classpath doesn't match, and main process's package"
+ + " has been updated since process launch; process needs"
+ + " restarting!");
+ } else {
+ // Crashing the process is unlikely to improve the situation - our classpath
+ // will probably be the same on next launch and probably still won't match.
+ // Log an error but just carry on and hope.
+ Log.e(
+ TAG,
+ "Child process's classpath doesn't match, but main process's package"
+ + " hasn't changed; the child is likely to be broken!");
}
- } else {
- recordChildAppInfoError(ChildAppInfoError.SUCCESS);
}
if (mServiceCallback != null) {
@@ -638,7 +644,7 @@
mServiceConnectComplete = true;
if (mMemoryPressureCallback == null) {
- final MemoryPressureCallback callback = this ::onMemoryPressure;
+ final MemoryPressureCallback callback = this::onMemoryPressure;
ThreadUtils.postOnUiThread(() -> MemoryPressureListener.addCallback(callback));
mMemoryPressureCallback = callback;
}
@@ -662,7 +668,10 @@
return;
}
mServiceDisconnected = true;
- Log.w(TAG, "onServiceDisconnected (crash or killed by oom): pid=%d %s", mPid,
+ Log.w(
+ TAG,
+ "onServiceDisconnected (crash or killed by oom): pid=%d %s",
+ mPid,
buildDebugStateString());
stop(); // We don't want to auto-restart on crash. Let the browser do that.
@@ -724,9 +733,7 @@
mConnectionCallback = null;
}
- /**
- * Passes the zygote bundle to the service.
- */
+ /** Passes the zygote bundle to the service. */
public void consumeZygoteBundle(Bundle zygoteBundle) {
if (mService == null) return;
try {
@@ -747,43 +754,53 @@
assert mServiceConnectComplete && mService != null;
assert mConnectionParams != null;
- IParentProcess parentProcess = new IParentProcess.Stub() {
- @Override
- public void finishSetupConnection(
- int pid, int zygotePid, long zygoteStartupTimeMillis, Bundle relroBundle) {
- mLauncherHandler.post(() -> {
- onSetupConnectionResultOnLauncherThread(
- pid, zygotePid, zygoteStartupTimeMillis, relroBundle);
- });
- }
-
- @Override
- public void reportExceptionInInit(String exception) {
- synchronized (mBindingStateLock) {
- mExceptionInServiceDuringInit = exception;
- }
- mLauncherHandler.post(createUnbindRunnable());
- }
-
- @Override
- public void reportCleanExit() {
- synchronized (mBindingStateLock) {
- mCleanExit = true;
- }
- mLauncherHandler.post(createUnbindRunnable());
- }
-
- private Runnable createUnbindRunnable() {
- return new Runnable() {
+ IParentProcess parentProcess =
+ new IParentProcess.Stub() {
@Override
- public void run() {
- unbind();
+ public void finishSetupConnection(
+ int pid,
+ int zygotePid,
+ long zygoteStartupTimeMillis,
+ Bundle relroBundle) {
+ mLauncherHandler.post(
+ () -> {
+ onSetupConnectionResultOnLauncherThread(
+ pid,
+ zygotePid,
+ zygoteStartupTimeMillis,
+ relroBundle);
+ });
+ }
+
+ @Override
+ public void reportExceptionInInit(String exception) {
+ synchronized (mBindingStateLock) {
+ mExceptionInServiceDuringInit = exception;
+ }
+ mLauncherHandler.post(createUnbindRunnable());
+ }
+
+ @Override
+ public void reportCleanExit() {
+ synchronized (mBindingStateLock) {
+ mCleanExit = true;
+ }
+ mLauncherHandler.post(createUnbindRunnable());
+ }
+
+ private Runnable createUnbindRunnable() {
+ return new Runnable() {
+ @Override
+ public void run() {
+ unbind();
+ }
+ };
}
};
- }
- };
try {
- mService.setupConnection(mConnectionParams.mConnectionBundle, parentProcess,
+ mService.setupConnection(
+ mConnectionParams.mConnectionBundle,
+ parentProcess,
mConnectionParams.mClientInterfaces);
} catch (RemoteException re) {
Log.e(TAG, "Failed to setup connection.", re);
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java
index 4285f87..872d49b 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java
@@ -4,9 +4,7 @@
package org.chromium.base.process_launcher;
-/**
- * Constants to be used by child processes.
- */
+/** Constants to be used by child processes. */
public interface ChildProcessConstants {
// Below are the names for the items placed in the bind or start command intent.
// Note that because that intent maybe reused if a service is restarted, none should be process
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java
index 5298815..999552b 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java
@@ -16,9 +16,7 @@
import java.io.IOException;
import java.util.List;
-/**
- * This class is used to start a child process by connecting to a ChildProcessService.
- */
+/** This class is used to start a child process by connecting to a ChildProcessService. */
public class ChildProcessLauncher {
private static final String TAG = "ChildProcLauncher";
@@ -112,10 +110,14 @@
* @param filesToBeMapped the files that should be passed to the started process.
* @param connectionAllocator the allocator used to create connections to the service.
* @param clientInterfaces the interfaces that should be passed to the started process so it can
- * communicate with the parent process.
+ * communicate with the parent process.
*/
- public ChildProcessLauncher(Handler launcherHandler, Delegate delegate, String[] commandLine,
- FileDescriptorInfo[] filesToBeMapped, ChildConnectionAllocator connectionAllocator,
+ public ChildProcessLauncher(
+ Handler launcherHandler,
+ Delegate delegate,
+ String[] commandLine,
+ FileDescriptorInfo[] filesToBeMapped,
+ ChildConnectionAllocator connectionAllocator,
List<IBinder> clientInterfaces) {
assert connectionAllocator != null;
mLauncherHandler = launcherHandler;
@@ -150,18 +152,20 @@
assert isRunningOnLauncherThread();
assert mConnection == connection;
Log.e(TAG, "ChildProcessConnection.start failed, trying again");
- mLauncherHandler.post(new Runnable() {
- @Override
- public void run() {
- // The child process may already be bound to another client
- // (this can happen if multi-process WebView is used in more
- // than one process), so try starting the process again.
- // This connection that failed to start has not been freed,
- // so a new bound connection will be allocated.
- mConnection = null;
- start(setupConnection, queueIfNoFreeConnection);
- }
- });
+ mLauncherHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ // The child process may already be bound to another
+ // client (this can happen if multi-process WebView is
+ // used in more than one process), so try starting the
+ // process again.
+ // This connection that failed to start has not been
+ // freed, so a new bound connection will be allocated.
+ mConnection = null;
+ start(setupConnection, queueIfNoFreeConnection);
+ }
+ });
}
@Override
@@ -177,7 +181,7 @@
return true;
}
if (!allocateAndSetupConnection(
- serviceCallback, setupConnection, queueIfNoFreeConnection)
+ serviceCallback, setupConnection, queueIfNoFreeConnection)
&& !queueIfNoFreeConnection) {
return false;
}
@@ -197,20 +201,23 @@
private boolean allocateAndSetupConnection(
final ChildProcessConnection.ServiceCallback serviceCallback,
- final boolean setupConnection, final boolean queueIfNoFreeConnection) {
+ final boolean setupConnection,
+ final boolean queueIfNoFreeConnection) {
assert mConnection == null;
Bundle serviceBundle = new Bundle();
mDelegate.onBeforeConnectionAllocated(serviceBundle);
- mConnection = mConnectionAllocator.allocate(
- ContextUtils.getApplicationContext(), serviceBundle, serviceCallback);
+ mConnection =
+ mConnectionAllocator.allocate(
+ ContextUtils.getApplicationContext(), serviceBundle, serviceCallback);
if (mConnection == null) {
if (!queueIfNoFreeConnection) {
Log.d(TAG, "Failed to allocate a child connection (no queuing).");
return false;
}
mConnectionAllocator.queueAllocation(
- () -> allocateAndSetupConnection(
+ () ->
+ allocateAndSetupConnection(
serviceCallback, setupConnection, queueIfNoFreeConnection));
return false;
}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java
index 45b83c2..9bc7d3b 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessService.java
@@ -87,6 +87,7 @@
// PID of the client of this service, set in bindToCaller(), if mBindToCallerCheck is true.
@GuardedBy("mBinderLock")
private int mBoundCallingPid;
+
@GuardedBy("mBinderLock")
private String mBoundCallingClazz;
@@ -117,121 +118,134 @@
}
// Binder object used by clients for this service.
- private final IChildProcessService.Stub mBinder = new IChildProcessService.Stub() {
- // NOTE: Implement any IChildProcessService methods here.
- @Override
- public boolean bindToCaller(String clazz) {
- assert mBindToCallerCheck;
- assert mServiceBound;
- synchronized (mBinderLock) {
- int callingPid = Binder.getCallingPid();
- if (mBoundCallingPid == 0 && mBoundCallingClazz == null) {
- mBoundCallingPid = callingPid;
- mBoundCallingClazz = clazz;
- } else if (mBoundCallingPid != callingPid) {
- Log.e(TAG, "Service is already bound by pid %d, cannot bind for pid %d",
- mBoundCallingPid, callingPid);
- return false;
- } else if (!TextUtils.equals(mBoundCallingClazz, clazz)) {
- Log.w(TAG, "Service is already bound by %s, cannot bind for %s",
- mBoundCallingClazz, clazz);
- return false;
+ private final IChildProcessService.Stub mBinder =
+ new IChildProcessService.Stub() {
+ // NOTE: Implement any IChildProcessService methods here.
+ @Override
+ public boolean bindToCaller(String clazz) {
+ assert mBindToCallerCheck;
+ assert mServiceBound;
+ synchronized (mBinderLock) {
+ int callingPid = Binder.getCallingPid();
+ if (mBoundCallingPid == 0 && mBoundCallingClazz == null) {
+ mBoundCallingPid = callingPid;
+ mBoundCallingClazz = clazz;
+ } else if (mBoundCallingPid != callingPid) {
+ Log.e(
+ TAG,
+ "Service is already bound by pid %d, cannot bind for pid %d",
+ mBoundCallingPid,
+ callingPid);
+ return false;
+ } else if (!TextUtils.equals(mBoundCallingClazz, clazz)) {
+ Log.w(
+ TAG,
+ "Service is already bound by %s, cannot bind for %s",
+ mBoundCallingClazz,
+ clazz);
+ return false;
+ }
+ }
+ return true;
}
- }
- return true;
- }
- @Override
- public ApplicationInfo getAppInfo() {
- return mApplicationContext.getApplicationInfo();
- }
-
- @Override
- public void setupConnection(Bundle args, IParentProcess parentProcess,
- List<IBinder> callbacks) throws RemoteException {
- assert mServiceBound;
- synchronized (mBinderLock) {
- if (mBindToCallerCheck && mBoundCallingPid == 0) {
- Log.e(TAG, "Service has not been bound with bindToCaller()");
- parentProcess.finishSetupConnection(-1, 0, 0, null);
- return;
+ @Override
+ public ApplicationInfo getAppInfo() {
+ return mApplicationContext.getApplicationInfo();
}
- }
- int pid = Process.myPid();
- int zygotePid = 0;
- long startupTimeMillis = -1;
- Bundle relroBundle = null;
- if (LibraryLoader.getInstance().isLoadedByZygote()) {
- zygotePid = sZygotePid;
- startupTimeMillis = sZygoteStartupTimeMillis;
- LibraryLoader.MultiProcessMediator m = LibraryLoader.getInstance().getMediator();
- m.initInChildProcess();
- // In a number of cases the app zygote decides not to produce a RELRO FD. The bundle
- // will tell the receiver to silently ignore it.
- relroBundle = new Bundle();
- m.putSharedRelrosToBundle(relroBundle);
- }
- // After finishSetupConnection() the parent process will stop accepting |relroBundle|
- // from this process to ensure that another FD to shared memory is not sent later.
- parentProcess.finishSetupConnection(pid, zygotePid, startupTimeMillis, relroBundle);
- mParentProcess = parentProcess;
- processConnectionBundle(args, callbacks);
- }
+ @Override
+ public void setupConnection(
+ Bundle args, IParentProcess parentProcess, List<IBinder> callbacks)
+ throws RemoteException {
+ assert mServiceBound;
+ synchronized (mBinderLock) {
+ if (mBindToCallerCheck && mBoundCallingPid == 0) {
+ Log.e(TAG, "Service has not been bound with bindToCaller()");
+ parentProcess.finishSetupConnection(-1, 0, 0, null);
+ return;
+ }
+ }
- @Override
- public void forceKill() {
- assert mServiceBound;
- Process.killProcess(Process.myPid());
- }
-
- @Override
- public void onMemoryPressure(@MemoryPressureLevel int pressure) {
- // This method is called by the host process when the host process reports pressure
- // to its native side. The key difference between the host process and its services is
- // that the host process polls memory pressure when it gets CRITICAL, and periodically
- // invokes pressure listeners until pressure subsides. (See MemoryPressureMonitor for
- // more info.)
- //
- // Services don't poll, so this side-channel is used to notify services about memory
- // pressure from the host process's POV.
- //
- // However, since both host process and services listen to ComponentCallbacks2, we
- // can't be sure that the host process won't get better signals than their services.
- // I.e. we need to watch out for a situation where a service gets CRITICAL, but the
- // host process gets MODERATE - in this case we need to ignore MODERATE.
- //
- // So we're ignoring pressure from the host process if it's better than the last
- // reported pressure. I.e. the host process can drive pressure up, but it'll go
- // down only when we the service get a signal through ComponentCallbacks2.
- ThreadUtils.postOnUiThread(() -> {
- if (pressure >= MemoryPressureMonitor.INSTANCE.getLastReportedPressure()) {
- MemoryPressureMonitor.INSTANCE.notifyPressure(pressure);
+ int pid = Process.myPid();
+ int zygotePid = 0;
+ long startupTimeMillis = -1;
+ Bundle relroBundle = null;
+ if (LibraryLoader.getInstance().isLoadedByZygote()) {
+ zygotePid = sZygotePid;
+ startupTimeMillis = sZygoteStartupTimeMillis;
+ LibraryLoader.MultiProcessMediator m =
+ LibraryLoader.getInstance().getMediator();
+ m.initInChildProcess();
+ // In a number of cases the app zygote decides not to produce a RELRO FD.
+ // The bundle will tell the receiver to silently ignore it.
+ relroBundle = new Bundle();
+ m.putSharedRelrosToBundle(relroBundle);
+ }
+ // After finishSetupConnection() the parent process will stop accepting
+ // |relroBundle| from this process to ensure that another FD to shared memory
+ // is not sent later.
+ parentProcess.finishSetupConnection(
+ pid, zygotePid, startupTimeMillis, relroBundle);
+ mParentProcess = parentProcess;
+ processConnectionBundle(args, callbacks);
}
- });
- }
- @Override
- public void dumpProcessStack() {
- assert mServiceBound;
- synchronized (mLibraryInitializedLock) {
- if (!mLibraryInitialized) {
- Log.e(TAG, "Cannot dump process stack before native is loaded");
- return;
+ @Override
+ public void forceKill() {
+ assert mServiceBound;
+ Process.killProcess(Process.myPid());
}
- }
- ChildProcessServiceJni.get().dumpProcessStack();
- }
- @Override
- public void consumeRelroBundle(Bundle bundle) {
- mDelegate.consumeRelroBundle(bundle);
- }
- };
+ @Override
+ public void onMemoryPressure(@MemoryPressureLevel int pressure) {
+ // This method is called by the host process when the host process reports
+ // pressure to its native side. The key difference between the host process
+ // and its services is that the host process polls memory pressure when it
+ // gets CRITICAL, and periodically invokes pressure listeners until pressure
+ // subsides. (See MemoryPressureMonitor for more info.)
+ //
+ // Services don't poll, so this side-channel is used to notify services about
+ // memory pressure from the host process's POV.
+ //
+ // However, since both host process and services listen to ComponentCallbacks2,
+ // we can't be sure that the host process won't get better signals than their
+ // services.
+ // I.e. we need to watch out for a situation where a service gets CRITICAL, but
+ // the host process gets MODERATE - in this case we need to ignore MODERATE.
+ //
+ // So we're ignoring pressure from the host process if it's better than the last
+ // reported pressure. I.e. the host process can drive pressure up, but it'll go
+ // down only when we the service get a signal through ComponentCallbacks2.
+ ThreadUtils.postOnUiThread(
+ () -> {
+ if (pressure
+ >= MemoryPressureMonitor.INSTANCE
+ .getLastReportedPressure()) {
+ MemoryPressureMonitor.INSTANCE.notifyPressure(pressure);
+ }
+ });
+ }
- /**
- * Loads Chrome's native libraries and initializes a ChildProcessService.
- */
+ @Override
+ public void dumpProcessStack() {
+ assert mServiceBound;
+ synchronized (mLibraryInitializedLock) {
+ if (!mLibraryInitialized) {
+ Log.e(TAG, "Cannot dump process stack before native is loaded");
+ return;
+ }
+ }
+ ChildProcessServiceJni.get().dumpProcessStack();
+ }
+
+ @Override
+ public void consumeRelroBundle(Bundle bundle) {
+ mDelegate.consumeRelroBundle(bundle);
+ }
+ };
+
+ /** Loads Chrome's native libraries and initializes a ChildProcessService. */
// For sCreateCalled check.
public void onCreate() {
Log.i(TAG, "Creating new ChildProcessService pid=%d", Process.myPid());
@@ -251,95 +265,94 @@
// default, which can be much smaller. So, explicitly set up a larger stack here.
long stackSize = ContextUtils.isProcess64Bit() ? 8 * 1024 * 1024 : 4 * 1024 * 1024;
- mMainThread = new Thread(/*threadGroup=*/null, new Runnable() {
- @Override
- public void run() {
- try {
- // CommandLine must be initialized before everything else.
- synchronized (mMainThread) {
- while (mCommandLineParams == null) {
- mMainThread.wait();
- }
- }
- assert mServiceBound;
- CommandLine.init(mCommandLineParams);
-
- if (CommandLine.getInstance().hasSwitch(
- BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) {
- android.os.Debug.waitForDebugger();
- }
-
- EarlyTraceEvent.onCommandLineAvailableInChildProcess();
- mDelegate.loadNativeLibrary(getApplicationContext());
-
- synchronized (mLibraryInitializedLock) {
- mLibraryInitialized = true;
- mLibraryInitializedLock.notifyAll();
- }
- synchronized (mMainThread) {
- mMainThread.notifyAll();
- while (mFdInfos == null) {
- mMainThread.wait();
- }
- }
-
- SparseArray<String> idsToKeys = mDelegate.getFileDescriptorsIdsToKeys();
-
- int[] fileIds = new int[mFdInfos.length];
- String[] keys = new String[mFdInfos.length];
- int[] fds = new int[mFdInfos.length];
- long[] regionOffsets = new long[mFdInfos.length];
- long[] regionSizes = new long[mFdInfos.length];
- for (int i = 0; i < mFdInfos.length; i++) {
- FileDescriptorInfo fdInfo = mFdInfos[i];
- String key = idsToKeys != null ? idsToKeys.get(fdInfo.id) : null;
- if (key != null) {
- keys[i] = key;
- } else {
- fileIds[i] = fdInfo.id;
- }
- fds[i] = fdInfo.fd.detachFd();
- regionOffsets[i] = fdInfo.offset;
- regionSizes[i] = fdInfo.size;
- }
- ChildProcessServiceJni.get().registerFileDescriptors(
- keys, fileIds, fds, regionOffsets, regionSizes);
-
- mDelegate.onBeforeMain();
- } catch (Throwable e) {
- try {
- mParentProcess.reportExceptionInInit(ChildProcessService.class.getName()
- + "\n" + android.util.Log.getStackTraceString(e));
- } catch (RemoteException re) {
- Log.e(TAG, "Failed to call reportExceptionInInit.", re);
- }
- throw new RuntimeException(e);
- }
-
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- // Record process startup time histograms.
- long startTime =
- SystemClock.uptimeMillis() - ApiHelperForN.getStartUptimeMillis();
- String baseHistogramName = "Android.ChildProcessStartTimeV2";
- String suffix = ContextUtils.isIsolatedProcess() ? ".Isolated" : ".NotIsolated";
- RecordHistogram.recordMediumTimesHistogram(
- baseHistogramName + ".All", startTime);
- RecordHistogram.recordMediumTimesHistogram(
- baseHistogramName + suffix, startTime);
- }
-
- mDelegate.runMain();
- try {
- mParentProcess.reportCleanExit();
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to call clean exit callback.", e);
- }
- ChildProcessServiceJni.get().exitChildProcess();
- }
- }, MAIN_THREAD_NAME, stackSize);
+ mMainThread =
+ new Thread(
+ /* threadGroup= */ null, this::mainThreadMain, MAIN_THREAD_NAME, stackSize);
mMainThread.start();
}
+ private void mainThreadMain() {
+ try {
+ // CommandLine must be initialized before everything else.
+ synchronized (mMainThread) {
+ while (mCommandLineParams == null) {
+ mMainThread.wait();
+ }
+ }
+ assert mServiceBound;
+ CommandLine.init(mCommandLineParams);
+
+ if (CommandLine.getInstance().hasSwitch(BaseSwitches.RENDERER_WAIT_FOR_JAVA_DEBUGGER)) {
+ android.os.Debug.waitForDebugger();
+ }
+
+ EarlyTraceEvent.onCommandLineAvailableInChildProcess();
+ mDelegate.loadNativeLibrary(getApplicationContext());
+
+ synchronized (mLibraryInitializedLock) {
+ mLibraryInitialized = true;
+ mLibraryInitializedLock.notifyAll();
+ }
+ synchronized (mMainThread) {
+ mMainThread.notifyAll();
+ while (mFdInfos == null) {
+ mMainThread.wait();
+ }
+ }
+
+ SparseArray<String> idsToKeys = mDelegate.getFileDescriptorsIdsToKeys();
+
+ int[] fileIds = new int[mFdInfos.length];
+ String[] keys = new String[mFdInfos.length];
+ int[] fds = new int[mFdInfos.length];
+ long[] regionOffsets = new long[mFdInfos.length];
+ long[] regionSizes = new long[mFdInfos.length];
+ for (int i = 0; i < mFdInfos.length; i++) {
+ FileDescriptorInfo fdInfo = mFdInfos[i];
+ String key = idsToKeys != null ? idsToKeys.get(fdInfo.id) : null;
+ if (key != null) {
+ keys[i] = key;
+ } else {
+ fileIds[i] = fdInfo.id;
+ }
+ fds[i] = fdInfo.fd.detachFd();
+ regionOffsets[i] = fdInfo.offset;
+ regionSizes[i] = fdInfo.size;
+ }
+ ChildProcessServiceJni.get()
+ .registerFileDescriptors(keys, fileIds, fds, regionOffsets, regionSizes);
+
+ mDelegate.onBeforeMain();
+ } catch (Throwable e) {
+ try {
+ mParentProcess.reportExceptionInInit(
+ ChildProcessService.class.getName()
+ + "\n"
+ + android.util.Log.getStackTraceString(e));
+ } catch (RemoteException re) {
+ Log.e(TAG, "Failed to call reportExceptionInInit.", re);
+ }
+ throw new RuntimeException(e);
+ }
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+ // Record process startup time histograms.
+ long startTime = SystemClock.uptimeMillis() - ApiHelperForN.getStartUptimeMillis();
+ String baseHistogramName = "Android.ChildProcessStartTimeV2";
+ String suffix = ContextUtils.isIsolatedProcess() ? ".Isolated" : ".NotIsolated";
+ RecordHistogram.recordMediumTimesHistogram(baseHistogramName + ".All", startTime);
+ RecordHistogram.recordMediumTimesHistogram(baseHistogramName + suffix, startTime);
+ }
+
+ mDelegate.runMain();
+ try {
+ mParentProcess.reportCleanExit();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to call clean exit callback.", e);
+ }
+ ChildProcessServiceJni.get().exitChildProcess();
+ }
+
@SuppressWarnings("checkstyle:SystemExitCheck") // Allowed due to http://crbug.com/928521#c16.
public void onDestroy() {
Log.i(TAG, "Destroying ChildProcessService pid=%d", Process.myPid());
@@ -425,14 +438,10 @@
*/
void registerFileDescriptors(String[] keys, int[] id, int[] fd, long[] offset, long[] size);
- /**
- * Force the child process to exit.
- */
+ /** Force the child process to exit. */
void exitChildProcess();
- /**
- * Dumps the child process stack without crashing it.
- */
+ /** Dumps the child process stack without crashing it. */
void dumpProcessStack();
}
}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java
index 7fa03ae..3e7f5c1 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java
@@ -12,9 +12,7 @@
import java.util.List;
-/**
- * The interface that embedders should implement to specialize child service creation.
- */
+/** The interface that embedders should implement to specialize child service creation. */
public interface ChildProcessServiceDelegate {
/** Invoked when the service was created. This is the first method invoked on the delegate. */
void onServiceCreated();
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java
index 0311406..560fe9d 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnection.java
@@ -7,8 +7,12 @@
/** Interface representing a connection to the Android service. Can be mocked in unit-tests. */
/* package */ interface ChildServiceConnection {
boolean bindServiceConnection();
+
void unbindServiceConnection();
+
boolean isBound();
+
void updateGroupImportance(int group, int importanceInGroup);
+
void retire();
}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionDelegate.java b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionDelegate.java
index a1cd101..3439856 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionDelegate.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionDelegate.java
@@ -12,5 +12,6 @@
*/
/* package */ interface ChildServiceConnectionDelegate {
void onServiceConnected(IBinder service);
+
void onServiceDisconnected();
}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionFactory.java b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionFactory.java
index cee40da..21b1521 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionFactory.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionFactory.java
@@ -7,6 +7,9 @@
import android.content.Intent;
/* package */ interface ChildServiceConnectionFactory {
- ChildServiceConnection createConnection(Intent bindIntent, int bindFlags,
- ChildServiceConnectionDelegate delegate, String instanceName);
+ ChildServiceConnection createConnection(
+ Intent bindIntent,
+ int bindFlags,
+ ChildServiceConnectionDelegate delegate,
+ String instanceName);
}
diff --git a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java
index 8dcbb3a..3a7f39c 100644
--- a/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java
+++ b/base/android/java/src/org/chromium/base/process_launcher/ChildServiceConnectionImpl.java
@@ -31,8 +31,13 @@
private final String mInstanceName;
private boolean mBound;
- /* package */ ChildServiceConnectionImpl(Context context, Intent bindIntent, int bindFlags,
- Handler handler, Executor executor, ChildServiceConnectionDelegate delegate,
+ /* package */ ChildServiceConnectionImpl(
+ Context context,
+ Intent bindIntent,
+ int bindFlags,
+ Handler handler,
+ Executor executor,
+ ChildServiceConnectionDelegate delegate,
String instanceName) {
mContext = context;
mBindIntent = bindIntent;
@@ -47,8 +52,15 @@
public boolean bindServiceConnection() {
try {
TraceEvent.begin("ChildServiceConnectionImpl.bindServiceConnection");
- mBound = BindService.doBindService(
- mContext, mBindIntent, this, mBindFlags, mHandler, mExecutor, mInstanceName);
+ mBound =
+ BindService.doBindService(
+ mContext,
+ mBindIntent,
+ this,
+ mBindFlags,
+ mHandler,
+ mExecutor,
+ mInstanceName);
} finally {
TraceEvent.end("ChildServiceConnectionImpl.bindServiceConnection");
}
diff --git a/base/android/java/src/org/chromium/base/shared_preferences/KeyPrefix.java b/base/android/java/src/org/chromium/base/shared_preferences/KeyPrefix.java
index 825dc58..5f4416d 100644
--- a/base/android/java/src/org/chromium/base/shared_preferences/KeyPrefix.java
+++ b/base/android/java/src/org/chromium/base/shared_preferences/KeyPrefix.java
@@ -25,6 +25,7 @@
public String createKey(String stem) {
return mPrefix + stem;
}
+
/**
* @param index An int to generate a unique key.
* @return The complete SharedPreferences key to be passed to {@link SharedPreferencesManager}.
diff --git a/base/android/java/src/org/chromium/base/shared_preferences/KnownPreferenceKeyRegistries.java b/base/android/java/src/org/chromium/base/shared_preferences/KnownPreferenceKeyRegistries.java
index 80f4a51..1c0c261 100644
--- a/base/android/java/src/org/chromium/base/shared_preferences/KnownPreferenceKeyRegistries.java
+++ b/base/android/java/src/org/chromium/base/shared_preferences/KnownPreferenceKeyRegistries.java
@@ -42,8 +42,8 @@
if (!sKnownRegistries.contains(registry)) {
String message =
"An unknown registry was used, PreferenceKeyRegistries must be declared as "
- + "known in AllPreferenceKeyRegistries: "
- + String.join(",", registry.toDebugString());
+ + "known in AllPreferenceKeyRegistries: "
+ + String.join(",", registry.toDebugString());
assert false : message;
}
}
@@ -70,8 +70,8 @@
}
String message =
"Unknown registries were used, PreferenceKeyRegistries must be declared as "
- + "known in AllPreferenceKeyRegistries: "
- + String.join(",", unknownRegistryNames);
+ + "known in AllPreferenceKeyRegistries: "
+ + String.join(",", unknownRegistryNames);
assert false : message;
}
@@ -84,10 +84,11 @@
Set<PreferenceKeyRegistry> registriesUsedBeforeInitialization =
sRegistriesUsedBeforeInitialization;
- ResettersForTesting.register(() -> {
- sKnownRegistries = previousKnownRegistries;
- sRegistriesUsedBeforeInitialization = registriesUsedBeforeInitialization;
- });
+ ResettersForTesting.register(
+ () -> {
+ sKnownRegistries = previousKnownRegistries;
+ sRegistriesUsedBeforeInitialization = registriesUsedBeforeInitialization;
+ });
sKnownRegistries = null;
sRegistriesUsedBeforeInitialization = new HashSet<>();
}
diff --git a/base/android/java/src/org/chromium/base/shared_preferences/NoOpPreferenceKeyChecker.java b/base/android/java/src/org/chromium/base/shared_preferences/NoOpPreferenceKeyChecker.java
index 344d8e4..8cea07c 100644
--- a/base/android/java/src/org/chromium/base/shared_preferences/NoOpPreferenceKeyChecker.java
+++ b/base/android/java/src/org/chromium/base/shared_preferences/NoOpPreferenceKeyChecker.java
@@ -4,9 +4,7 @@
package org.chromium.base.shared_preferences;
-/**
- * A placeholder key checker that never throws exceptions. Used in production builds.
- */
+/** A placeholder key checker that never throws exceptions. Used in production builds. */
class NoOpPreferenceKeyChecker implements PreferenceKeyChecker {
@Override
public void checkIsKeyInUse(String key) {
diff --git a/base/android/java/src/org/chromium/base/shared_preferences/PreferenceKeyRegistry.java b/base/android/java/src/org/chromium/base/shared_preferences/PreferenceKeyRegistry.java
index 410ea2a..2d6badd 100644
--- a/base/android/java/src/org/chromium/base/shared_preferences/PreferenceKeyRegistry.java
+++ b/base/android/java/src/org/chromium/base/shared_preferences/PreferenceKeyRegistry.java
@@ -19,7 +19,10 @@
public final HashSet<String> mLegacyFormatKeys;
public final List<KeyPrefix> mLegacyPrefixes;
- public PreferenceKeyRegistry(String module, List<String> keysInUse, List<String> legacyKeys,
+ public PreferenceKeyRegistry(
+ String module,
+ List<String> keysInUse,
+ List<String> legacyKeys,
List<KeyPrefix> legacyPrefixes) {
mModule = module;
mKeysInUse = new HashSet<>(keysInUse);
@@ -29,7 +32,12 @@
@NonNull
public String toDebugString() {
- return String.format(Locale.getDefault(), "%s (%d in use, %d legacy, %d legacy prefixes)",
- mModule, mKeysInUse.size(), mLegacyFormatKeys.size(), mLegacyPrefixes.size());
+ return String.format(
+ Locale.getDefault(),
+ "%s (%d in use, %d legacy, %d legacy prefixes)",
+ mModule,
+ mKeysInUse.size(),
+ mLegacyFormatKeys.size(),
+ mLegacyPrefixes.size());
}
}
diff --git a/base/android/java/src/org/chromium/base/shared_preferences/SharedPreferencesManager.java b/base/android/java/src/org/chromium/base/shared_preferences/SharedPreferencesManager.java
index d5bd240..a125ae2 100644
--- a/base/android/java/src/org/chromium/base/shared_preferences/SharedPreferencesManager.java
+++ b/base/android/java/src/org/chromium/base/shared_preferences/SharedPreferencesManager.java
@@ -24,9 +24,7 @@
import java.util.Map;
import java.util.Set;
-/**
- * Layer over android {@link SharedPreferences}.
- */
+/** Layer over android {@link SharedPreferences}. */
@JNINamespace("base::android")
@SuppressWarnings("UseSharedPreferencesManagerFromChromeCheck")
public class SharedPreferencesManager {
@@ -36,8 +34,10 @@
private PreferenceKeyChecker mKeyChecker;
protected SharedPreferencesManager(PreferenceKeyRegistry registry) {
- mKeyChecker = BuildConfig.ENABLE_ASSERTS ? new StrictPreferenceKeyChecker(registry)
- : new NoOpPreferenceKeyChecker();
+ mKeyChecker =
+ BuildConfig.ENABLE_ASSERTS
+ ? new StrictPreferenceKeyChecker(registry)
+ : new NoOpPreferenceKeyChecker();
}
@VisibleForTesting
@@ -95,42 +95,38 @@
return (values != null) ? Collections.unmodifiableSet(values) : null;
}
- /**
- * Adds a value to string set in shared preferences.
- */
+ /** Adds a value to string set in shared preferences. */
public void addToStringSet(String key, String value) {
mKeyChecker.checkIsKeyInUse(key);
// Construct a new set so it can be modified safely. See crbug.com/568369.
- Set<String> values = new HashSet<>(
- ContextUtils.getAppSharedPreferences().getStringSet(key, Collections.emptySet()));
+ Set<String> values =
+ new HashSet<>(
+ ContextUtils.getAppSharedPreferences()
+ .getStringSet(key, Collections.emptySet()));
values.add(value);
writeStringSetUnchecked(key, values);
}
- /**
- * Removes value from string set in shared preferences.
- */
+ /** Removes value from string set in shared preferences. */
public void removeFromStringSet(String key, String value) {
mKeyChecker.checkIsKeyInUse(key);
// Construct a new set so it can be modified safely. See crbug.com/568369.
- Set<String> values = new HashSet<>(
- ContextUtils.getAppSharedPreferences().getStringSet(key, Collections.emptySet()));
+ Set<String> values =
+ new HashSet<>(
+ ContextUtils.getAppSharedPreferences()
+ .getStringSet(key, Collections.emptySet()));
if (values.remove(value)) {
writeStringSetUnchecked(key, values);
}
}
- /**
- * Writes string set to shared preferences.
- */
+ /** Writes string set to shared preferences. */
public void writeStringSet(String key, Set<String> values) {
mKeyChecker.checkIsKeyInUse(key);
writeStringSetUnchecked(key, values);
}
- /**
- * Writes string set to shared preferences.
- */
+ /** Writes string set to shared preferences. */
private void writeStringSetUnchecked(String key, Set<String> values) {
Editor editor = ContextUtils.getAppSharedPreferences().edit().putStringSet(key, values);
editor.apply();
diff --git a/base/android/java/src/org/chromium/base/shared_preferences/StrictPreferenceKeyChecker.java b/base/android/java/src/org/chromium/base/shared_preferences/StrictPreferenceKeyChecker.java
index 3b84739..91721d9 100644
--- a/base/android/java/src/org/chromium/base/shared_preferences/StrictPreferenceKeyChecker.java
+++ b/base/android/java/src/org/chromium/base/shared_preferences/StrictPreferenceKeyChecker.java
@@ -40,8 +40,10 @@
@Override
public void checkIsKeyInUse(String key) {
if (!isKeyInUse(key)) {
- throw new RuntimeException("SharedPreferences key \"" + key
- + "\" is not registered in PreferenceKeyRegistry.mKeysInUse");
+ throw new RuntimeException(
+ "SharedPreferences key \""
+ + key
+ + "\" is not registered in PreferenceKeyRegistry.mKeysInUse");
}
KnownPreferenceKeyRegistries.onRegistryUsed(mRegistry);
}
@@ -96,7 +98,9 @@
return;
}
- throw new RuntimeException("SharedPreferences KeyPrefix \"" + prefix.pattern()
- + "\" is not registered in PreferenceKeyRegistry.mKeysInUse()");
+ throw new RuntimeException(
+ "SharedPreferences KeyPrefix \""
+ + prefix.pattern()
+ + "\" is not registered in PreferenceKeyRegistry.mKeysInUse()");
}
}
diff --git a/base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java b/base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java
index ac50cd6..f429eab 100644
--- a/base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java
+++ b/base/android/java/src/org/chromium/base/supplier/ObservableSupplier.java
@@ -39,4 +39,4 @@
* @param obs The observer to remove.
*/
void removeObserver(Callback<E> obs);
-}
\ No newline at end of file
+}
diff --git a/base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java b/base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java
index 10a629f..744d8d7 100644
--- a/base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java
+++ b/base/android/java/src/org/chromium/base/supplier/ObservableSupplierImpl.java
@@ -49,10 +49,11 @@
if (mObject != null) {
final E currentObject = mObject;
- mHandler.post(() -> {
- if (mObject != currentObject || !mObservers.hasObserver(obs)) return;
- obs.onResult(mObject);
- });
+ mHandler.post(
+ () -> {
+ if (mObject != currentObject || !mObservers.hasObserver(obs)) return;
+ obs.onResult(mObject);
+ });
}
return mObject;
@@ -96,10 +97,8 @@
}
private void checkThread() {
- assert sIgnoreThreadChecksForTesting
- || mThread
- == Thread.currentThread()
- : "ObservableSupplierImpl must only be used on a single Thread.";
+ assert sIgnoreThreadChecksForTesting || mThread == Thread.currentThread()
+ : "ObservableSupplierImpl must only be used on a single Thread.";
}
/** Used to allow developers to access supplier values on the instrumentation thread. */
diff --git a/base/android/java/src/org/chromium/base/supplier/OneShotCallback.java b/base/android/java/src/org/chromium/base/supplier/OneShotCallback.java
index eefb535..2c0c8ca 100644
--- a/base/android/java/src/org/chromium/base/supplier/OneShotCallback.java
+++ b/base/android/java/src/org/chromium/base/supplier/OneShotCallback.java
@@ -50,9 +50,9 @@
public void onResult(E result) {
mCallback.onResult(result);
ObservableSupplier<E> supplier = mWeakSupplier.get();
- assert supplier
- != null : "This can only be called by supplier, which should not be null.";
+ assert supplier != null
+ : "This can only be called by supplier, which should not be null.";
supplier.removeObserver(mCallbackWrapper);
}
}
-}
\ No newline at end of file
+}
diff --git a/base/android/java/src/org/chromium/base/supplier/SupplierUtils.java b/base/android/java/src/org/chromium/base/supplier/SupplierUtils.java
new file mode 100644
index 0000000..b4fe503
--- /dev/null
+++ b/base/android/java/src/org/chromium/base/supplier/SupplierUtils.java
@@ -0,0 +1,82 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base.supplier;
+
+import androidx.annotation.NonNull;
+
+import org.chromium.base.Callback;
+import org.chromium.base.ThreadUtils;
+
+/** Utilities for interactions with Suppliers. */
+public class SupplierUtils {
+ private SupplierUtils() {}
+
+ private static class Barrier {
+ private final ThreadUtils.ThreadChecker mThreadChecker = new ThreadUtils.ThreadChecker();
+ private int mWaitingCount;
+ private Runnable mCallback;
+
+ void waitForAll(Runnable callback, Supplier... suppliers) {
+ mThreadChecker.assertOnValidThread();
+ assert mCallback == null;
+ mCallback = callback;
+ int waitingSupplierCount = 0;
+ Callback<?> supplierCallback = (unused) -> onSupplierAvailable();
+ for (Supplier<?> supplier : suppliers) {
+ if (supplier.hasValue()) continue;
+
+ waitingSupplierCount++;
+ if (supplier instanceof ObservableSupplier) {
+ ObservableSupplier<?> observableSupplier = ((ObservableSupplier) supplier);
+ new OneShotCallback(observableSupplier, supplierCallback);
+ } else if (supplier instanceof OneshotSupplier) {
+ ((OneshotSupplier) supplier).onAvailable(supplierCallback);
+ } else if (supplier instanceof SyncOneshotSupplier) {
+ ((SyncOneshotSupplier) supplier).onAvailable(supplierCallback);
+ } else {
+ assert false
+ : "Unexpected Supplier type that does not already have a value: "
+ + supplier;
+ }
+ }
+ mWaitingCount = waitingSupplierCount;
+ notifyCallbackIfAppropriate();
+ }
+
+ private void onSupplierAvailable() {
+ mThreadChecker.assertOnValidThread();
+ mWaitingCount--;
+ assert mWaitingCount >= 0;
+ notifyCallbackIfAppropriate();
+ }
+
+ private void notifyCallbackIfAppropriate() {
+ if (mWaitingCount != 0) return;
+ if (mCallback == null) return;
+ mCallback.run();
+ mCallback = null;
+ }
+ }
+
+ /**
+ * Waits for all suppliers to have assigned values, and when that happens, notifies the
+ * specified callback.
+ *
+ * <p>If all suppliers already have values, then the callback will be notified synchronously.
+ *
+ * <p>To prevent leaking objects, it is recommended to use {@link
+ * org.chromium.base.CallbackController} for the {@link Runnable} callback.
+ *
+ * <p>Not thread safe. All passed in suppliers must be notified on the same thread this method
+ * is called.
+ *
+ * @param callback The callback to be notified when all suppliers have values set.
+ * @param suppliers The list of suppliers to check for values.
+ */
+ public static void waitForAll(@NonNull Runnable callback, Supplier... suppliers) {
+ assert callback != null;
+ new Barrier().waitForAll(callback, suppliers);
+ }
+}
diff --git a/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java b/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java
index 2fcce55..c11b78a 100644
--- a/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java
+++ b/base/android/java/src/org/chromium/base/supplier/UnownedUserDataSupplier.java
@@ -14,39 +14,36 @@
import org.chromium.base.lifetime.Destroyable;
/**
- * UnownedUserDataSupplier handles the combined lifecycle management for {@link UnownedUserData}
- * and {@link DestroyableObservableSupplier}. It can be constructed anywhere
- * but needs to be attached before it's accessible via {@link UnownedUserDataHost}. When destroyed,
- * UnownedUserDataSupplier is detached from all hosts.
+ * UnownedUserDataSupplier handles the combined lifecycle management for {@link UnownedUserData} and
+ * {@link DestroyableObservableSupplier}. It can be constructed anywhere but needs to be attached
+ * before it's accessible via {@link UnownedUserDataHost}. When destroyed, UnownedUserDataSupplier
+ * is detached from all hosts.
*
- * <p>
- * A functional implementation with best practices is defined in
- * {@link UnownedUserDataSupplierTest}.
- * <p>
- * Classes that hold a reference to to the concrete implementation of this class are also in charge
- * of its lifecycle. {@link #destroy} should be called when the applciation is shutting down. This
- * will detach the {@link UnownedUserDataSupplier}, but it won't destroy the supplied object.
- * <p>
- * In practice, UnownedUserDataSupplier owners should declare and assign the supplier inline. This
- * allows interop between other supplier implementations as well as use in activity constructors
- * before {@link WindowAndroid} is created. See the example below:
+ * <p>A functional implementation with best practices is defined in {@link
+ * UnownedUserDataSupplierTest}.
*
- * <pre>
- * {@code
+ * <p>Classes that hold a reference to to the concrete implementation of this class are also in
+ * charge of its lifecycle. {@link #destroy} should be called when the application is shutting down.
+ * This will detach the {@link UnownedUserDataSupplier}, but it won't destroy the supplied object.
+ *
+ * <p>In practice, UnownedUserDataSupplier owners should declare and assign the supplier inline.
+ * This allows interop between other supplier implementations as well as use in activity
+ * constructors before {@link WindowAndroid} is created. See the example below:
+ *
+ * <pre>{@code
* UnownedUserDataSupplier<Foo> mFooSupplier = new FooSupplier();
* ...
* // Sometime after WindowAndroid has been created.
* mFooSupplier.attach(mWindowAndroid.getUnownedUserDataHost());
- * }
- * </pre>
+ * }</pre>
*
* @param <E> The type of the data to be Supplied and stored in UnownedUserData.
* @see UnownedUserDataHost for more details on ownership and typical usage.
* @see UnownedUserDataKey for information about the type of key that is required.
* @see UnownedUserData for the marker interface used for this type of data.
*/
-public abstract class UnownedUserDataSupplier<E>
- extends ObservableSupplierImpl<E> implements Destroyable, UnownedUserData {
+public abstract class UnownedUserDataSupplier<E> extends ObservableSupplierImpl<E>
+ implements Destroyable, UnownedUserData {
private final UnownedUserDataKey<UnownedUserDataSupplier<E>> mUudKey;
private final DestroyChecker mDestroyChecker = new DestroyChecker();
diff --git a/base/android/java/src/org/chromium/base/task/AsyncTask.java b/base/android/java/src/org/chromium/base/task/AsyncTask.java
index e45d508..a4fc623 100644
--- a/base/android/java/src/org/chromium/base/task/AsyncTask.java
+++ b/base/android/java/src/org/chromium/base/task/AsyncTask.java
@@ -82,21 +82,16 @@
@IntDef({Status.PENDING, Status.RUNNING, Status.FINISHED})
@Retention(RetentionPolicy.SOURCE)
public @interface Status {
- /**
- * Indicates that the task has not been executed yet.
- */
+ /** Indicates that the task has not been executed yet. */
int PENDING = 0;
- /**
- * Indicates that the task is running.
- */
+
+ /** Indicates that the task is running. */
int RUNNING = 1;
- /**
- * Indicates that {@link AsyncTask#onPostExecute} has finished.
- */
+
+ /** Indicates that {@link AsyncTask#onPostExecute} has finished. */
int FINISHED = 2;
- /**
- * Just used for reporting this status to UMA.
- */
+
+ /** Just used for reporting this status to UMA. */
int NUM_ENTRIES = 3;
}
@@ -107,27 +102,23 @@
exec.shutdown();
}
- /**
- * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
- */
+ /** Creates a new asynchronous task. This constructor must be invoked on the UI thread. */
public AsyncTask() {
- mWorker = new Callable<Result>() {
- @Override
- public Result call() throws Exception {
- mTaskInvoked.set(true);
- Result result = null;
- try {
- result = doInBackground();
- Binder.flushPendingCommands();
- } catch (Throwable tr) {
- mCancelled.set(true);
- throw tr;
- } finally {
- postResult(result);
- }
- return result;
- }
- };
+ mWorker =
+ () -> {
+ mTaskInvoked.set(true);
+ Result result = null;
+ try {
+ result = doInBackground();
+ Binder.flushPendingCommands();
+ } catch (Throwable tr) {
+ mCancelled.set(true);
+ throw tr;
+ } finally {
+ postResult(result);
+ }
+ return result;
+ };
mFuture = new NamedFutureTask(mWorker);
}
@@ -144,7 +135,10 @@
if (this instanceof BackgroundOnlyAsyncTask) {
mStatus = Status.FINISHED;
} else if (mIterationIdForTesting == PostTask.sTestIterationForTesting) {
- ThreadUtils.postOnUiThread(() -> { finish(result); });
+ ThreadUtils.postOnUiThread(
+ () -> {
+ finish(result);
+ });
}
}
@@ -370,12 +364,13 @@
if (mStatus != Status.PENDING) {
switch (mStatus) {
case Status.RUNNING:
- throw new IllegalStateException("Cannot execute task:"
- + " the task is already running.");
+ throw new IllegalStateException(
+ "Cannot execute task:" + " the task is already running.");
case Status.FINISHED:
- throw new IllegalStateException("Cannot execute task:"
- + " the task has already been executed "
- + "(a task can be executed only once)");
+ throw new IllegalStateException(
+ "Cannot execute task:"
+ + " the task has already been executed "
+ + "(a task can be executed only once)");
}
}
@@ -469,8 +464,8 @@
@Override
@SuppressWarnings("NoDynamicStringsInTraceEventCheck")
public void run() {
- try (TraceEvent e = TraceEvent.scoped(
- "AsyncTask.run: " + mFuture.getBlamedClass().getName())) {
+ try (TraceEvent e =
+ TraceEvent.scoped("AsyncTask.run: " + mFuture.getBlamedClass().getName())) {
super.run();
} finally {
// Clear the interrupt on this background thread, if there is one, as it likely
diff --git a/base/android/java/src/org/chromium/base/task/ChainedTasks.java b/base/android/java/src/org/chromium/base/task/ChainedTasks.java
index 24ac55b..1a9dd30 100644
--- a/base/android/java/src/org/chromium/base/task/ChainedTasks.java
+++ b/base/android/java/src/org/chromium/base/task/ChainedTasks.java
@@ -28,28 +28,32 @@
*/
public class ChainedTasks {
private final LinkedList<Pair<Integer, Runnable>> mTasks = new LinkedList<>();
+
@GuardedBy("mTasks")
private boolean mFinalized;
+
private volatile boolean mCanceled;
private int mIterationIdForTesting = PostTask.sTestIterationForTesting;
- private final Runnable mRunAndPost = new Runnable() {
- @Override
- @SuppressWarnings("NoDynamicStringsInTraceEventCheck")
- public void run() {
- if (mIterationIdForTesting != PostTask.sTestIterationForTesting) {
- cancel();
- }
- if (mCanceled) return;
+ private final Runnable mRunAndPost =
+ new Runnable() {
+ @Override
+ @SuppressWarnings("NoDynamicStringsInTraceEventCheck")
+ public void run() {
+ if (mIterationIdForTesting != PostTask.sTestIterationForTesting) {
+ cancel();
+ }
+ if (mCanceled) return;
- Pair<Integer, Runnable> pair = mTasks.pop();
- try (TraceEvent e = TraceEvent.scoped(
- "ChainedTask.run: " + pair.second.getClass().getName())) {
- pair.second.run();
- }
- if (!mTasks.isEmpty()) PostTask.postTask(mTasks.peek().first, this);
- }
- };
+ Pair<Integer, Runnable> pair = mTasks.pop();
+ try (TraceEvent e =
+ TraceEvent.scoped(
+ "ChainedTask.run: " + pair.second.getClass().getName())) {
+ pair.second.run();
+ }
+ if (!mTasks.isEmpty()) PostTask.postTask(mTasks.peek().first, this);
+ }
+ };
/**
* Adds a task to the list of tasks to run. Cannot be called once {@link start()} has been
@@ -64,9 +68,7 @@
}
}
- /**
- * Cancels the remaining tasks.
- */
+ /** Cancels the remaining tasks. */
public void cancel() {
synchronized (mTasks) {
mFinalized = true;
@@ -82,20 +84,21 @@
*/
public void start(final boolean coalesceTasks) {
synchronized (mTasks) {
- assert !mFinalized :"Cannot call start() several times";
+ assert !mFinalized : "Cannot call start() several times";
mFinalized = true;
}
if (mTasks.isEmpty()) return;
if (coalesceTasks) {
- @TaskTraits
- int traits = mTasks.peek().first;
- PostTask.runOrPostTask(traits, () -> {
- for (Pair<Integer, Runnable> pair : mTasks) {
- assert PostTask.canRunTaskImmediately(pair.first);
- pair.second.run();
- if (mCanceled) return;
- }
- });
+ @TaskTraits int traits = mTasks.peek().first;
+ PostTask.runOrPostTask(
+ traits,
+ () -> {
+ for (Pair<Integer, Runnable> pair : mTasks) {
+ assert PostTask.canRunTaskImmediately(pair.first);
+ pair.second.run();
+ if (mCanceled) return;
+ }
+ });
} else {
PostTask.postTask(mTasks.peek().first, mRunAndPost);
}
diff --git a/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java b/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java
index 4e525cf..8b885d4 100644
--- a/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java
+++ b/base/android/java/src/org/chromium/base/task/ChromeThreadPoolExecutor.java
@@ -31,13 +31,15 @@
private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
private static final int KEEP_ALIVE_SECONDS = 30;
- private static final ThreadFactory sThreadFactory = new ThreadFactory() {
- private final AtomicInteger mCount = new AtomicInteger(1);
- @Override
- public Thread newThread(Runnable r) {
- return new Thread(r, "CrAsyncTask #" + mCount.getAndIncrement());
- }
- };
+ private static final ThreadFactory sThreadFactory =
+ new ThreadFactory() {
+ private final AtomicInteger mCount = new AtomicInteger(1);
+
+ @Override
+ public Thread newThread(Runnable r) {
+ return new Thread(r, "CrAsyncTask #" + mCount.getAndIncrement());
+ }
+ };
private static final BlockingQueue<Runnable> sPoolWorkQueue =
new ArrayBlockingQueue<Runnable>(128);
@@ -46,13 +48,23 @@
private static final int RUNNABLE_WARNING_COUNT = 32;
ChromeThreadPoolExecutor() {
- this(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, SECONDS, sPoolWorkQueue,
+ this(
+ CORE_POOL_SIZE,
+ MAXIMUM_POOL_SIZE,
+ KEEP_ALIVE_SECONDS,
+ SECONDS,
+ sPoolWorkQueue,
sThreadFactory);
}
@VisibleForTesting
- ChromeThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
- TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
+ ChromeThreadPoolExecutor(
+ int corePoolSize,
+ int maximumPoolSize,
+ long keepAliveTime,
+ TimeUnit unit,
+ BlockingQueue<Runnable> workQueue,
+ ThreadFactory threadFactory) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
allowCoreThreadTimeOut(true);
}
diff --git a/base/android/java/src/org/chromium/base/task/PostTask.java b/base/android/java/src/org/chromium/base/task/PostTask.java
index f4a3774..c135fb1 100644
--- a/base/android/java/src/org/chromium/base/task/PostTask.java
+++ b/base/android/java/src/org/chromium/base/task/PostTask.java
@@ -31,6 +31,7 @@
public class PostTask {
private static final String TAG = "PostTask";
private static final Object sPreNativeTaskRunnerLock = new Object();
+
@GuardedBy("sPreNativeTaskRunnerLock")
private static List<TaskRunnerImpl> sPreNativeTaskRunners = new ArrayList<>();
@@ -186,9 +187,7 @@
ResettersForTesting.register(() -> sPrenativeThreadPoolExecutorForTesting = null);
}
- /**
- * Clears an override set by setPrenativeThreadPoolExecutorOverrideForTesting.
- */
+ /** Clears an override set by setPrenativeThreadPoolExecutorOverrideForTesting. */
public static void resetPrenativeThreadPoolExecutorForTesting() {
sPrenativeThreadPoolExecutorForTesting = null;
}
diff --git a/base/android/java/src/org/chromium/base/task/SerialExecutor.java b/base/android/java/src/org/chromium/base/task/SerialExecutor.java
index 1d00d91..c43acee 100644
--- a/base/android/java/src/org/chromium/base/task/SerialExecutor.java
+++ b/base/android/java/src/org/chromium/base/task/SerialExecutor.java
@@ -13,16 +13,14 @@
@Override
public synchronized void execute(final Runnable r) {
- mTasks.offer(new Runnable() {
- @Override
- public void run() {
- try {
- r.run();
- } finally {
- scheduleNext();
- }
- }
- });
+ mTasks.offer(
+ () -> {
+ try {
+ r.run();
+ } finally {
+ scheduleNext();
+ }
+ });
if (mActive == null) {
scheduleNext();
}
diff --git a/base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java b/base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java
index e999d83..a971683 100644
--- a/base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java
+++ b/base/android/java/src/org/chromium/base/task/SingleThreadTaskRunnerImpl.java
@@ -17,8 +17,7 @@
*/
@JNINamespace("base")
public class SingleThreadTaskRunnerImpl extends TaskRunnerImpl implements SingleThreadTaskRunner {
- @Nullable
- private final Handler mHandler;
+ @Nullable private final Handler mHandler;
/**
* @param handler The backing Handler if any. Note this must run tasks on the
diff --git a/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java b/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java
index b525e09..8387bdb 100644
--- a/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java
+++ b/base/android/java/src/org/chromium/base/task/TaskRunnerImpl.java
@@ -33,6 +33,7 @@
// TaskRunnerCleaners are enqueued to this queue when their WeakReference to a TaskRunnerIml is
// cleared.
private static final ReferenceQueue<Object> sQueue = new ReferenceQueue<>();
+
// Holds a strong reference to the pending TaskRunnerCleaners so they don't get GC'd before the
// TaskRunnerImpl they're weakly referencing does.
@GuardedBy("sCleaners")
@@ -49,11 +50,14 @@
protected final Runnable mRunPreNativeTaskClosure = this::runPreNativeTask;
private final Object mPreNativeTaskLock = new Object();
+
@GuardedBy("mPreNativeTaskLock")
private boolean mDidOneTimeInitialization;
+
@Nullable
@GuardedBy("mPreNativeTaskLock")
private LinkedList<Runnable> mPreNativeTasks;
+
@Nullable
@GuardedBy("mPreNativeTaskLock")
private List<Pair<Runnable, Long>> mPreNativeDelayedTasks;
@@ -144,15 +148,17 @@
public void postDelayedTask(Runnable task, long delay) {
// Lock-free path when native is initialized.
if (mNativeTaskRunnerAndroid != 0) {
- TaskRunnerImplJni.get().postDelayedTask(
- mNativeTaskRunnerAndroid, task, delay, task.getClass().getName());
+ TaskRunnerImplJni.get()
+ .postDelayedTask(
+ mNativeTaskRunnerAndroid, task, delay, task.getClass().getName());
return;
}
synchronized (mPreNativeTaskLock) {
oneTimeInitialization();
if (mNativeTaskRunnerAndroid != 0) {
- TaskRunnerImplJni.get().postDelayedTask(
- mNativeTaskRunnerAndroid, task, delay, task.getClass().getName());
+ TaskRunnerImplJni.get()
+ .postDelayedTask(
+ mNativeTaskRunnerAndroid, task, delay, task.getClass().getName());
return;
}
// We don't expect a whole lot of these, if that changes consider pooling them.
@@ -211,9 +217,7 @@
return false;
}
- /**
- * Runs a single task and returns when its finished.
- */
+ /** Runs a single task and returns when its finished. */
// The trace event name is derived from string literals.
@SuppressWarnings("NoDynamicStringsInTraceEventCheck")
protected void runPreNativeTask() {
@@ -236,15 +240,15 @@
case TaskTraits.USER_BLOCKING_MAY_BLOCK:
Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);
break;
- // We don't want to lower the Thread Priority of the UI Thread, especially
- // pre-native, as the Thread is oversubscribed, highly latency sensitive, and
- // there's only a single task queue so low priority tasks can run ahead of high
- // priority tasks.
+ // We don't want to lower the Thread Priority of the UI Thread, especially
+ // pre-native, as the Thread is oversubscribed, highly latency sensitive, and
+ // there's only a single task queue so low priority tasks can run ahead of high
+ // priority tasks.
case TaskTraits.UI_BEST_EFFORT: // Fall-through.
case TaskTraits.UI_USER_VISIBLE: // Fall-through.
case TaskTraits.UI_USER_BLOCKING: // Fall-through.
break;
- // lint ensures all cases are checked.
+ // lint ensures all cases are checked.
}
task.run();
}
@@ -259,15 +263,20 @@
synchronized (mPreNativeTaskLock) {
if (mPreNativeTasks != null) {
for (Runnable task : mPreNativeTasks) {
- TaskRunnerImplJni.get().postDelayedTask(
- nativeTaskRunnerAndroid, task, 0, task.getClass().getName());
+ TaskRunnerImplJni.get()
+ .postDelayedTask(
+ nativeTaskRunnerAndroid, task, 0, task.getClass().getName());
}
mPreNativeTasks = null;
}
if (mPreNativeDelayedTasks != null) {
for (Pair<Runnable, Long> task : mPreNativeDelayedTasks) {
- TaskRunnerImplJni.get().postDelayedTask(nativeTaskRunnerAndroid, task.first,
- task.second, task.getClass().getName());
+ TaskRunnerImplJni.get()
+ .postDelayedTask(
+ nativeTaskRunnerAndroid,
+ task.first,
+ task.second,
+ task.getClass().getName());
}
mPreNativeDelayedTasks = null;
}
@@ -290,9 +299,12 @@
@NativeMethods
interface Natives {
long init(@TaskRunnerType int taskRunnerType, @TaskTraits int taskTraits);
+
void destroy(long nativeTaskRunnerAndroid);
+
void postDelayedTask(
long nativeTaskRunnerAndroid, Runnable task, long delay, String runnableClassName);
+
boolean belongsToCurrentThread(long nativeTaskRunnerAndroid);
}
}
diff --git a/base/android/java_exception_reporter.cc b/base/android/java_exception_reporter.cc
index 8c078e4..05d7786 100644
--- a/base/android/java_exception_reporter.cc
+++ b/base/android/java_exception_reporter.cc
@@ -12,6 +12,7 @@
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/lazy_instance.h"
+#include "base/logging.h"
using base::android::JavaParamRef;
using base::android::JavaRef;
diff --git a/base/android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java b/base/android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java
index 938c140..9a73514 100644
--- a/base/android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java
+++ b/base/android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java
@@ -14,14 +14,10 @@
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
-/**
- * Test class for {@link CommandLineInitUtil}.
- */
+/** Test class for {@link CommandLineInitUtil}. */
@RunWith(AndroidJUnit4.class)
public class CommandLineInitUtilTest {
- /**
- * Verifies that the default command line flags get set for Chrome Public tests.
- */
+ /** Verifies that the default command line flags get set for Chrome Public tests. */
@Test
@SmallTest
@Feature({"CommandLine"})
diff --git a/base/android/javatests/src/org/chromium/base/LocaleUtilsTest.java b/base/android/javatests/src/org/chromium/base/LocaleUtilsTest.java
index 64f1144..946863e 100644
--- a/base/android/javatests/src/org/chromium/base/LocaleUtilsTest.java
+++ b/base/android/javatests/src/org/chromium/base/LocaleUtilsTest.java
@@ -21,9 +21,7 @@
import java.util.Locale;
-/**
- * Tests for the LocaleUtils class.
- */
+/** Tests for the LocaleUtils class. */
@RunWith(BaseJUnit4ClassRunner.class)
@Batch(Batch.UNIT_TESTS)
public class LocaleUtilsTest {
diff --git a/base/android/javatests/src/org/chromium/base/ObserverListTest.java b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
index 8e031bd..08b6300 100644
--- a/base/android/javatests/src/org/chromium/base/ObserverListTest.java
+++ b/base/android/javatests/src/org/chromium/base/ObserverListTest.java
@@ -17,9 +17,7 @@
import java.util.Iterator;
import java.util.NoSuchElementException;
-/**
- * Tests for (@link ObserverList}.
- */
+/** Tests for (@link ObserverList}. */
@RunWith(BaseJUnit4ClassRunner.class)
public class ObserverListTest {
interface Observer {
@@ -40,9 +38,7 @@
}
}
- /**
- * An observer which add a given Observer object to the list when observe is called.
- */
+ /** An observer which add a given Observer object to the list when observe is called. */
private static class FooAdder implements Observer {
private final ObserverList<Observer> mList;
private final Observer mLucky;
@@ -58,9 +54,7 @@
}
}
- /**
- * An observer which removes a given Observer object from the list when observe is called.
- */
+ /** An observer which removes a given Observer object from the list when observe is called. */
private static class FooRemover implements Observer {
private final ObserverList<Observer> mList;
private final Observer mDoomed;
diff --git a/base/android/javatests/src/org/chromium/base/UserDataHostTest.java b/base/android/javatests/src/org/chromium/base/UserDataHostTest.java
index ff3a3bc..a4c44b7 100644
--- a/base/android/javatests/src/org/chromium/base/UserDataHostTest.java
+++ b/base/android/javatests/src/org/chromium/base/UserDataHostTest.java
@@ -12,9 +12,7 @@
import org.chromium.base.test.BaseJUnit4ClassRunner;
-/**
- * Test class for {@link UserDataHost}.
- */
+/** Test class for {@link UserDataHost}. */
@RunWith(BaseJUnit4ClassRunner.class)
public class UserDataHostTest {
private final UserDataHost mHost = new UserDataHost();
@@ -72,9 +70,7 @@
}
}
- /**
- * Verifies basic operations.
- */
+ /** Verifies basic operations. */
@Test
@SmallTest
public void testBasicOperations() {
@@ -86,9 +82,7 @@
removeUserDataException(TestObjectA.class, IllegalStateException.class);
}
- /**
- * Verifies nulled key or data are not allowed.
- */
+ /** Verifies nulled key or data are not allowed. */
@Test
@SmallTest
public void testNullKeyOrDataAreDisallowed() {
@@ -100,9 +94,7 @@
removeUserDataException(null, IllegalArgumentException.class);
}
- /**
- * Verifies {@link #setUserData()} overwrites current data.
- */
+ /** Verifies {@link #setUserData()} overwrites current data. */
@Test
@SmallTest
public void testSetUserDataOverwrites() {
@@ -115,9 +107,7 @@
Assert.assertEquals(obj2, mHost.getUserData(TestObjectA.class));
}
- /**
- * Verifies operation on a different thread is not allowed.
- */
+ /** Verifies operation on a different thread is not allowed. */
@Test
@SmallTest
public void testSingleThreadPolicy() {
@@ -127,9 +117,7 @@
() -> getUserDataException(TestObjectA.class, IllegalStateException.class));
}
- /**
- * Verifies {@link UserHostData#destroy()} detroyes each {@link UserData} object.
- */
+ /** Verifies {@link UserHostData#destroy()} detroyes each {@link UserData} object. */
@Test
@SmallTest
public void testDestroy() {
@@ -145,9 +133,7 @@
Assert.assertTrue(objB.isDestroyed());
}
- /**
- * Verifies that no operation is allowed after {@link #destroy()} is called.
- */
+ /** Verifies that no operation is allowed after {@link #destroy()} is called. */
@Test
@SmallTest
public void testOperationsDisallowedAfterDestroy() {
diff --git a/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java b/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
index 7c9071d..c6f7d36 100644
--- a/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
+++ b/base/android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java
@@ -14,9 +14,7 @@
import org.chromium.base.library_loader.LibraryLoader;
import org.chromium.base.test.BaseJUnit4ClassRunner;
-/**
- * Tests for the Java API for recording UMA histograms.
- */
+/** Tests for the Java API for recording UMA histograms. */
@RunWith(BaseJUnit4ClassRunner.class)
public class RecordHistogramTest {
@Before
@@ -24,9 +22,7 @@
LibraryLoader.getInstance().ensureInitialized();
}
- /**
- * Tests recording of boolean histograms.
- */
+ /** Tests recording of boolean histograms. */
@Test
@SmallTest
public void testRecordBooleanHistogram() {
@@ -49,9 +45,7 @@
Assert.assertEquals(1, falseCount.getDelta());
}
- /**
- * Tests recording of enumerated histograms.
- */
+ /** Tests recording of enumerated histograms. */
@Test
@SmallTest
public void testRecordEnumeratedHistogram() {
@@ -81,9 +75,7 @@
Assert.assertEquals(1, twoCount.getDelta());
}
- /**
- * Tests recording of count histograms.
- */
+ /** Tests recording of count histograms. */
@Test
@SmallTest
public void testRecordCount1MHistogram() {
@@ -123,9 +115,7 @@
Assert.assertEquals(1, eightThousandCount.getDelta());
}
- /**
- * Tests recording of custom times histograms.
- */
+ /** Tests recording of custom times histograms. */
@Test
@SmallTest
public void testRecordCustomTimesHistogram() {
@@ -159,9 +149,7 @@
Assert.assertEquals(1, twoCount.getDelta());
}
- /**
- * Tests recording of linear count histograms.
- */
+ /** Tests recording of linear count histograms. */
@Test
@SmallTest
public void testRecordLinearCountHistogram() {
diff --git a/base/android/javatests/src/org/chromium/base/profiler/TestSupport.java b/base/android/javatests/src/org/chromium/base/profiler/TestSupport.java
index be6f003..4b1fc5d 100644
--- a/base/android/javatests/src/org/chromium/base/profiler/TestSupport.java
+++ b/base/android/javatests/src/org/chromium/base/profiler/TestSupport.java
@@ -8,9 +8,7 @@
import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
-/**
- * Helper to run code through JNI layer to test JNI unwinding.
- */
+/** Helper to run code through JNI layer to test JNI unwinding. */
@JNINamespace("base")
public final class TestSupport {
@CalledByNative
diff --git a/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherTestBase.java b/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherTestBase.java
index 2903e15..1a51b10 100644
--- a/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherTestBase.java
+++ b/base/android/javatests/src/org/chromium/base/test/metrics/HistogramWatcherTestBase.java
@@ -28,8 +28,11 @@
protected static final String EXACT_LINEAR_HISTOGRAM_3 = "ExactLinearHistogram3"; // max 30
protected static final String ENUM_HISTOGRAM = "EnumHistogram"; // max 10
- @IntDef({TestScenario.WITHOUT_NATIVE, TestScenario.TRANSITION_TO_NATIVE,
- TestScenario.WITH_NATIVE})
+ @IntDef({
+ TestScenario.WITHOUT_NATIVE,
+ TestScenario.TRANSITION_TO_NATIVE,
+ TestScenario.WITH_NATIVE
+ })
protected @interface TestScenario {
int WITHOUT_NATIVE = 0;
int TRANSITION_TO_NATIVE = 1;
@@ -61,11 +64,12 @@
protected void doTestFourTimesHistograms_success(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
- .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
- .expectIntRecordTimes(TIMES_HISTOGRAM_1, 8000, 2)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
+ .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
+ .expectIntRecordTimes(TIMES_HISTOGRAM_1, 8000, 2)
+ .build();
// Act
RecordHistogram.recordTimesHistogram(TIMES_HISTOGRAM_1, 6000);
@@ -81,11 +85,12 @@
protected void doTestExtraRecord_failure(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
- .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
- .expectIntRecordTimes(TIMES_HISTOGRAM_1, 8000, 2)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
+ .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
+ .expectIntRecordTimes(TIMES_HISTOGRAM_1, 8000, 2)
+ .build();
// Act
RecordHistogram.recordTimesHistogram(TIMES_HISTOGRAM_1, 6000);
@@ -112,12 +117,13 @@
protected void doTestExtraRecordAllowed_success(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(ENUM_HISTOGRAM, 6)
- .expectIntRecord(ENUM_HISTOGRAM, 7)
- .expectIntRecordTimes(ENUM_HISTOGRAM, 8, 2)
- .allowExtraRecordsForHistogramsAbove()
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(ENUM_HISTOGRAM, 6)
+ .expectIntRecord(ENUM_HISTOGRAM, 7)
+ .expectIntRecordTimes(ENUM_HISTOGRAM, 8, 2)
+ .allowExtraRecordsForHistogramsAbove()
+ .build();
// Act
RecordHistogram.recordEnumeratedHistogram(ENUM_HISTOGRAM, 6, 10);
@@ -135,12 +141,13 @@
protected void doTestExtraRecordAllowed_failure(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(ENUM_HISTOGRAM, 6)
- .expectIntRecord(ENUM_HISTOGRAM, 7)
- .expectIntRecordTimes(ENUM_HISTOGRAM, 8, 2)
- .allowExtraRecordsForHistogramsAbove()
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(ENUM_HISTOGRAM, 6)
+ .expectIntRecord(ENUM_HISTOGRAM, 7)
+ .expectIntRecordTimes(ENUM_HISTOGRAM, 8, 2)
+ .allowExtraRecordsForHistogramsAbove()
+ .build();
// Act
RecordHistogram.recordEnumeratedHistogram(ENUM_HISTOGRAM, 6, 10);
@@ -165,10 +172,11 @@
protected void doTestExtraRecordAllowedAny_success(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectAnyRecordTimes(BOOLEAN_HISTOGRAM, 3)
- .allowExtraRecordsForHistogramsAbove()
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectAnyRecordTimes(BOOLEAN_HISTOGRAM, 3)
+ .allowExtraRecordsForHistogramsAbove()
+ .build();
// Act
RecordHistogram.recordBooleanHistogram(BOOLEAN_HISTOGRAM, false);
@@ -184,10 +192,11 @@
protected void doTestExtraRecordAllowedAny_failure(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectAnyRecordTimes(BOOLEAN_HISTOGRAM, 3)
- .allowExtraRecordsForHistogramsAbove()
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectAnyRecordTimes(BOOLEAN_HISTOGRAM, 3)
+ .allowExtraRecordsForHistogramsAbove()
+ .build();
// Act
RecordHistogram.recordBooleanHistogram(BOOLEAN_HISTOGRAM, false);
@@ -209,11 +218,12 @@
protected void doTestMissingLastRecord_failure(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
- .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
- .expectIntRecordTimes(TIMES_HISTOGRAM_1, 8000, 2)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
+ .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
+ .expectIntRecordTimes(TIMES_HISTOGRAM_1, 8000, 2)
+ .build();
// Act
RecordHistogram.recordTimesHistogram(TIMES_HISTOGRAM_1, 6000);
@@ -319,14 +329,15 @@
protected void doTestMultipleHistograms_success(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_1, 5)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_1, 6)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_2, 15)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_2, 16)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_3, 25)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_3, 26)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_1, 5)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_1, 6)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_2, 15)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_2, 16)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_3, 25)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_3, 26)
+ .build();
// Act
RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 5, 10);
@@ -344,14 +355,15 @@
protected void doTestMultipleHistograms_failure(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_1, 5)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_1, 6)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_2, 15)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_2, 16)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_3, 25)
- .expectIntRecord(EXACT_LINEAR_HISTOGRAM_3, 26)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_1, 5)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_1, 6)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_2, 15)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_2, 16)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_3, 25)
+ .expectIntRecord(EXACT_LINEAR_HISTOGRAM_3, 26)
+ .build();
// Act
RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 5, 10);
@@ -377,9 +389,10 @@
protected void doTestExpectIntRecords_success(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecords(EXACT_LINEAR_HISTOGRAM_1, 5, 7, 6, 5)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecords(EXACT_LINEAR_HISTOGRAM_1, 5, 7, 6, 5)
+ .build();
// Act
RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 6, 10);
@@ -395,9 +408,10 @@
protected void doTestExpectIntRecords_failure(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecords(EXACT_LINEAR_HISTOGRAM_1, 5, 7, 6, 5)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecords(EXACT_LINEAR_HISTOGRAM_1, 5, 7, 6, 5)
+ .build();
// Act
RecordHistogram.recordExactLinearHistogram(EXACT_LINEAR_HISTOGRAM_1, 6, 10);
@@ -436,11 +450,12 @@
protected void doTestMissingFirstRecord_failure(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
- .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
- .expectIntRecord(TIMES_HISTOGRAM_1, 8000)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
+ .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
+ .expectIntRecord(TIMES_HISTOGRAM_1, 8000)
+ .build();
// Act
RecordHistogram.recordTimesHistogram(TIMES_HISTOGRAM_1, 7000);
@@ -463,11 +478,12 @@
protected void doTestMissingMiddleRecord_failure(@TestScenario int scenario) {
// Arrange
maybeLoadNativeFirst(scenario);
- mWatcher = HistogramWatcher.newBuilder()
- .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
- .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
- .expectIntRecord(TIMES_HISTOGRAM_1, 8000)
- .build();
+ mWatcher =
+ HistogramWatcher.newBuilder()
+ .expectIntRecord(TIMES_HISTOGRAM_1, 6000)
+ .expectIntRecord(TIMES_HISTOGRAM_1, 7000)
+ .expectIntRecord(TIMES_HISTOGRAM_1, 8000)
+ .build();
// Act
RecordHistogram.recordTimesHistogram(TIMES_HISTOGRAM_1, 6000);
@@ -502,8 +518,10 @@
protected static void assertContains(String expectedSubstring, String actualString) {
Assert.assertNotNull(actualString);