blob: 7c2e4dc885c274f73f5de90cd46292f3442693fa [file] [log] [blame]
/*
* Copyright (C) 2014 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.idea.monitor.memory;
import com.android.ddmlib.Client;
import com.android.ddmlib.IDevice;
import com.android.tools.chartlib.EventData;
import com.android.tools.chartlib.TimelineComponent;
import com.android.tools.chartlib.TimelineData;
import com.android.tools.idea.ddms.DeviceContext;
import com.android.tools.idea.ddms.actions.GcAction;
import com.android.tools.idea.ddms.actions.ToggleAllocationTrackingAction;
import com.android.tools.idea.ddms.hprof.DumpHprofAction;
import com.android.tools.idea.monitor.BaseMonitorView;
import com.android.tools.idea.monitor.DeviceSampler;
import com.android.tools.idea.monitor.TimelineEventListener;
import com.android.tools.idea.monitor.actions.RecordingAction;
import com.android.tools.idea.monitor.memory.actions.ToggleDebugRender;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComponentWithActions;
import com.intellij.ui.JBColor;
import com.intellij.util.ui.UIUtil;
import icons.AndroidIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.HierarchyListener;
import static com.android.tools.idea.startup.AndroidStudioSpecificInitializer.ENABLE_EXPERIMENTAL_ACTIONS;
public class MemoryMonitorView extends BaseMonitorView implements HierarchyListener, DeviceContext.DeviceSelectionListener {
/**
* Maximum number of samples to keep in memory. We not only sample at {@code SAMPLE_FREQUENCY_MS} but we also receive
* a sample on every GC.
*/
public static final int SAMPLES = 2048;
private static final Color BACKGROUND_COLOR = UIUtil.getTextFieldBackground();
private static final int SAMPLE_FREQUENCY_MS = 500;
@NotNull private final DeviceContext myDeviceContext;
@NotNull private TimelineComponent myTimelineComponent;
@NotNull private MemorySampler myMemorySampler;
private final EventData myEvents;
public static final int EVENT_HPROF = 1;
public static final int EVENT_ALLOC = 2;
public MemoryMonitorView(@NotNull Project project, @NotNull DeviceContext deviceContext) {
super(project);
myDeviceContext = deviceContext;
// Buffer at one and a half times the sample frequency.
float bufferTimeInSeconds = SAMPLE_FREQUENCY_MS * 1.5f / 1000.f;
float initialMax = 5.0f;
float initialMarker = 2.0f;
TimelineData data = new TimelineData(2, SAMPLES);
myEvents = new EventData();
myTimelineComponent = new TimelineComponent(data, myEvents, bufferTimeInSeconds, initialMax, Float.MAX_VALUE, initialMarker);
myTimelineComponent.configureUnits("MB");
myTimelineComponent.configureStream(0, "Allocated", new JBColor(0x78abd9, 0x78abd9));
myTimelineComponent.configureStream(1, "Free", new JBColor(0xbaccdc, 0x51585c));
myTimelineComponent
.configureEvent(EVENT_HPROF, 0, AndroidIcons.Ddms.DumpHprof, new JBColor(0x92ADC6, 0x718493), new JBColor(0x2B4E8C, 0xC7E5FF), false);
myTimelineComponent
.configureEvent(EVENT_ALLOC, 0, AndroidIcons.Ddms.AllocationTracker, new JBColor(0x92ADC6, 0x718493), new JBColor(0x2B4E8C, 0xC7E5FF),
true);
myTimelineComponent.configureType(DeviceSampler.TYPE_DATA, TimelineComponent.Style.SOLID);
myTimelineComponent.configureType(DeviceSampler.TYPE_TIMEOUT, TimelineComponent.Style.DASHED);
myTimelineComponent.setBackground(BACKGROUND_COLOR);
setComponent(myTimelineComponent);
myMemorySampler = new MemorySampler(data, SAMPLE_FREQUENCY_MS);
myMemorySampler.addListener(this);
myContentPane.addHierarchyListener(this);
myDeviceContext.addListener(this, project);
}
@NotNull
public ActionGroup getToolbarActions() {
DefaultActionGroup group = new DefaultActionGroup();
if (Boolean.getBoolean(ENABLE_EXPERIMENTAL_ACTIONS)) {
group.add(new RecordingAction(myMemorySampler));
}
group.add(new GcAction(myDeviceContext));
group.add(new DumpHprofAction(myProject, myDeviceContext, myEvents));
group.add(new ToggleAllocationTrackingAction(myDeviceContext, myEvents));
if (Boolean.getBoolean("studio.profiling.debug")) {
group.addSeparator();
group.add(new ToggleDebugRender(myTimelineComponent));
}
return group;
}
@NotNull
public ComponentWithActions createComponent() {
return new ComponentWithActions.Impl(getToolbarActions(), null, null, null, myContentPane);
}
@Override
public void deviceSelected(@Nullable IDevice device) {
}
@Override
public void deviceChanged(@NotNull IDevice device, int changeMask) {
}
@Override
public void clientSelected(@Nullable Client c) {
myMemorySampler.setClient(c);
}
@Override
protected DeviceSampler getSampler() {
return myMemorySampler;
}
}