blob: 64ddf5ba53dd0a3c03211e1acf56473d415aa919 [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/jni_android.h"
#include "base/memory/ptr_util.h"
#include "content/browser/memory/memory_coordinator_impl.h"
#include "jni/MemoryMonitorAndroid_jni.h"
namespace content {
namespace {
const size_t kMBShift = 20;
void RegisterComponentCallbacks() {
Java_MemoryMonitorAndroid_registerComponentCallbacks(
base::android::AttachCurrentThread());
}
}
// 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, reinterpret_cast<intptr_t>(out));
}
// Called by JNI to populate ActivityManager.MemoryInfo.
static void JNI_MemoryMonitorAndroid_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 = 80;
const int kTrimMemoryRunningCritical = 15;
// Called by JNI.
static void JNI_MemoryMonitorAndroid_OnTrimMemory(
JNIEnv* env,
const base::android::JavaParamRef<jclass>& jcaller,
jint level) {
DCHECK(level >= 0 && level <= kTrimMemoryLevelMax);
auto* coordinator = MemoryCoordinatorImpl::GetInstance();
DCHECK(coordinator);
if (level >= kTrimMemoryRunningCritical) {
coordinator->ForceSetMemoryCondition(MemoryCondition::CRITICAL,
base::TimeDelta::FromMinutes(1));
}
}
// static
std::unique_ptr<MemoryMonitorAndroid> MemoryMonitorAndroid::Create() {
auto delegate = base::WrapUnique(new MemoryMonitorAndroidDelegateImpl);
return base::WrapUnique(new MemoryMonitorAndroid(std::move(delegate)));
}
MemoryMonitorAndroid::MemoryMonitorAndroid(std::unique_ptr<Delegate> delegate)
: delegate_(std::move(delegate)) {
DCHECK(delegate_.get());
RegisterComponentCallbacks();
application_state_listener_ =
std::make_unique<base::android::ApplicationStatusListener>(
base::Bind(&MemoryMonitorAndroid::OnApplicationStateChange,
base::Unretained(this)));
}
MemoryMonitorAndroid::~MemoryMonitorAndroid() {}
int MemoryMonitorAndroid::GetFreeMemoryUntilCriticalMB() {
MemoryInfo info;
GetMemoryInfo(&info);
return (info.avail_mem - info.threshold) >> kMBShift;
}
void MemoryMonitorAndroid::GetMemoryInfo(MemoryInfo* out) {
delegate_->GetMemoryInfo(out);
}
void MemoryMonitorAndroid::OnApplicationStateChange(
base::android::ApplicationState state) {
auto* coordinator = MemoryCoordinatorImpl::GetInstance();
if (!coordinator)
return;
if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
coordinator->OnForegrounded();
} else if (state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES) {
coordinator->OnBackgrounded();
}
}
// Implementation of a factory function defined in memory_monitor.h.
std::unique_ptr<MemoryMonitor> CreateMemoryMonitor() {
return MemoryMonitorAndroid::Create();
}
} // namespace content