blob: 9d144d05690e06cc86189707f5da5c8dcbc84adf [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/memory/memory_monitor_android.h"
#include "base/android/context_utils.h"
#include "base/android/jni_android.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "content/browser/memory/memory_coordinator.h"
#include "jni/MemoryMonitorAndroid_jni.h"
namespace content {
namespace {
const size_t kMBShift = 20;
void RegisterComponentCallbacks() {
Java_MemoryMonitorAndroid_registerComponentCallbacks(
base::android::AttachCurrentThread(),
base::android::GetApplicationContext());
}
}
// An implementation of MemoryMonitorAndroid::Delegate using the Android APIs.
class MemoryMonitorAndroidDelegateImpl : public MemoryMonitorAndroid::Delegate {
public:
MemoryMonitorAndroidDelegateImpl() {}
~MemoryMonitorAndroidDelegateImpl() override {}
using MemoryInfo = MemoryMonitorAndroid::MemoryInfo;
void GetMemoryInfo(MemoryInfo* out) override;
private:
DISALLOW_COPY_AND_ASSIGN(MemoryMonitorAndroidDelegateImpl);
};
void MemoryMonitorAndroidDelegateImpl::GetMemoryInfo(MemoryInfo* out) {
DCHECK(out);
JNIEnv* env = base::android::AttachCurrentThread();
Java_MemoryMonitorAndroid_getMemoryInfo(
env, base::android::GetApplicationContext(),
reinterpret_cast<intptr_t>(out));
}
// Called by JNI to populate ActivityManager.MemoryInfo.
static void GetMemoryInfoCallback(
JNIEnv* env,
const base::android::JavaParamRef<jclass>& clazz,
jlong avail_mem,
jboolean low_memory,
jlong threshold,
jlong total_mem,
jlong out_ptr) {
DCHECK(out_ptr);
MemoryMonitorAndroid::MemoryInfo* info =
reinterpret_cast<MemoryMonitorAndroid::MemoryInfo*>(out_ptr);
info->avail_mem = avail_mem;
info->low_memory = low_memory;
info->threshold = threshold;
info->total_mem = total_mem;
}
// The maximum level of onTrimMemory (TRIM_MEMORY_COMPLETE).
const int kTrimMemoryLevelMax = 0x80;
// Called by JNI.
static void OnTrimMemory(JNIEnv* env,
const base::android::JavaParamRef<jclass>& jcaller,
jint level) {
DCHECK(level >= 0 && level <= kTrimMemoryLevelMax);
auto state = MemoryCoordinator::GetInstance()->GetGlobalMemoryState();
switch (state) {
case base::MemoryState::NORMAL:
UMA_HISTOGRAM_ENUMERATION("Memory.Coordinator.TrimMemoryLevel.Normal",
level, kTrimMemoryLevelMax);
break;
case base::MemoryState::THROTTLED:
UMA_HISTOGRAM_ENUMERATION("Memory.Coordinator.TrimMemoryLevel.Throttled",
level, kTrimMemoryLevelMax);
break;
case base::MemoryState::SUSPENDED:
UMA_HISTOGRAM_ENUMERATION("Memory.Coordinator.TrimMemoryLevel.Suspended",
level, kTrimMemoryLevelMax);
break;
case base::MemoryState::UNKNOWN:
NOTREACHED();
break;
}
}
// static
std::unique_ptr<MemoryMonitorAndroid> MemoryMonitorAndroid::Create() {
auto delegate = base::WrapUnique(new MemoryMonitorAndroidDelegateImpl);
return base::WrapUnique(new MemoryMonitorAndroid(std::move(delegate)));
}
// static
bool MemoryMonitorAndroid::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
MemoryMonitorAndroid::MemoryMonitorAndroid(std::unique_ptr<Delegate> delegate)
: delegate_(std::move(delegate)) {
DCHECK(delegate_.get());
RegisterComponentCallbacks();
}
MemoryMonitorAndroid::~MemoryMonitorAndroid() {}
int MemoryMonitorAndroid::GetFreeMemoryUntilCriticalMB() {
MemoryInfo info;
GetMemoryInfo(&info);
return (info.avail_mem - info.threshold) >> kMBShift;
}
void MemoryMonitorAndroid::GetMemoryInfo(MemoryInfo* out) {
delegate_->GetMemoryInfo(out);
}
// Implementation of a factory function defined in memory_monitor.h.
std::unique_ptr<MemoryMonitor> CreateMemoryMonitor() {
return MemoryMonitorAndroid::Create();
}
} // namespace content