android:layout_height="?android:attr/listPreferredItemHeight"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
-
<com.android.settings.applications.LinearColorBar
android:id="@+id/linear_color_bar"
android:layout_width="match_parent"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipToPadding="false"
+ android:scrollbarStyle="@integer/preference_scrollbar_style">
+
+ <LinearLayout
+ android:id="@+id/all_details"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="5dip"
+ android:paddingBottom="5dip"
+ android:orientation="vertical">
+
+ <TextView
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:text="@string/mem_state_subtitle" />
+
+ <LinearLayout
+ android:id="@+id/mem_state"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="6dip"
+ android:orientation="vertical">
+
+ <!-- Insert detail items here -->
+
+ </LinearLayout>
+
+ <TextView
+ style="?android:attr/listSeparatorTextViewStyle"
+ android:text="@string/mem_use_subtitle" />
+
+ <LinearLayout
+ android:id="@+id/mem_use"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingStart="6dip"
+ android:orientation="vertical">
+
+ <!-- Insert detail items here -->
+
+ </LinearLayout>
+
+ </LinearLayout>
+</ScrollView>
<item>15</item>
<item>20</item>
</integer-array>
+
+ <!-- Process stats memory use details: labels for memory states -->
+ <string-array name="proc_stats_memory_states" >
+ <item>Normal</item>
+ <item>Moderate</item>
+ <item>Low</item>
+ <item>Critical</item>
+ </string-array>
+
+ <!-- Process stats memory use details: labels for process -->
+ <string-array name="proc_stats_process_states" >
+ <item>Persistent</item>
+ <item>Top activity</item>
+ <item>Important (foreground)</item>
+ <item>Important (background)</item>
+ <item>Backup</item>
+ <item>Heavy weight</item>
+ <item>Service (running)</item>
+ <item>Service (restarting)</item>
+ <item>Receiver</item>
+ <item>Home</item>
+ <item>Last activity</item>
+ <item>Cached (activity)</item>
+ <item>Cached (activity client)</item>
+ <item>Cached (empty)</item>
+ </string-array>
</resources>
<string name="services_subtitle">Services</string>
<!-- [CHAR LIMIT=NONE] Menu for process stats to select duration of stats to show -->
<string name="menu_proc_stats_duration">Duration</string>
+ <!-- [CHAR LIMIT=NONE] Activity title for process stats details on overall memory state -->
+ <string name="mem_details_title">Memory details</string>
+ <!-- [CHAR LIMIT=NONE] Subtitle for process stats memory state details for list of memory states -->
+ <string name="mem_state_subtitle">Memory states</string>
+ <!-- [CHAR LIMIT=NONE] Subtitle for process stats memory state details for list of memory use -->
+ <string name="mem_use_subtitle">Memory use</string>
+ <!-- [CHAR LIMIT=NONE] Type of memory use associated with the kernel -->
+ <string name="mem_use_kernel_type">Kernel</string>
+ <!-- [CHAR LIMIT=NONE] Type of memory use associated with native processes -->
+ <string name="mem_use_native_type">Native</string>
+ <!-- [CHAR LIMIT=NONE] Type of memory use associated with kernel caches -->
+ <string name="mem_use_kernel_cache_type">Kernel caches</string>
+ <!-- [CHAR LIMIT=NONE] Type of memory use associated with kernel zram swap -->
+ <string name="mem_use_zram_type">ZRam swap</string>
+ <!-- [CHAR LIMIT=NONE] Type of memory use that is available/free -->
+ <string name="mem_use_free_type">Free</string>
+ <!-- [CHAR LIMIT=NONE] Total of all memory use -->
+ <string name="mem_use_total">Total</string>
<!-- [CHAR LIMIT=NONE] Menu for process stats to show 3 hours of data -->
<string name="menu_duration_3h">3 hours</string>
<!-- [CHAR LIMIT=NONE] Menu for process stats to show 3 hours of data -->
public static final float DISABLED_ALPHA = 0.4f;
/**
+ * Color spectrum to use to indicate badness. 0 is completely transparent (no data),
+ * 1 is most bad (red), the last value is least bad (green).
+ */
+ public static final int[] BADNESS_COLORS = new int[] {
+ 0x00000000, 0xffc43828, 0xffe54918, 0xfff47b00,
+ 0xfffabf2c, 0xff679e37, 0xff0a7f42
+ };
+
+ /**
* Name of the meta-data item that should be set in the AndroidManifest.xml
* to specify the icon that should be displayed for the preference.
*/
float mRedRatio;
float mYellowRatio;
float mGreenRatio;
+ int mRedColor = 0xffaa5030;
+ int mYellowColor = 0xffaaaa30;
+ int mGreenColor = 0xff30aa50;
int mColoredRegions = LinearColorBar.REGION_ALL;
LinearColorBar.OnRegionTappedListener mOnRegionTappedListener;
notifyChanged();
}
+ public void setColors(int red, int yellow, int green) {
+ mRedColor = red;
+ mYellowColor = yellow;
+ mGreenColor = green;
+ notifyChanged();
+ }
+
public void setOnRegionTappedListener(LinearColorBar.OnRegionTappedListener listener) {
mOnRegionTappedListener = listener;
notifyChanged();
LinearColorBar colors = (LinearColorBar)view.findViewById(
R.id.linear_color_bar);
colors.setShowIndicator(false);
- colors.setColors(0xffaa5030, 0xffaaaa30, 0xff30aa50);
+ colors.setColors(mRedColor, mYellowColor, mGreenColor);
colors.setRatios(mRedRatio, mYellowRatio, mGreenRatio);
colors.setColoredRegions(mColoredRegions);
colors.setOnRegionTappedListener(mOnRegionTappedListener);
--- /dev/null
+/*
+ * 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.settings.applications;
+
+import android.app.Fragment;
+import android.os.Bundle;
+import android.text.format.Formatter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+import com.android.internal.app.ProcessStats;
+import com.android.settings.R;
+
+import static com.android.settings.Utils.prepareCustomPreferencesList;
+
+public class ProcessStatsMemDetail extends Fragment {
+ public static final String EXTRA_MEM_TIMES = "mem_times";
+ public static final String EXTRA_MEM_STATE_WEIGHTS = "mem_state_weights";
+ public static final String EXTRA_MEM_CACHED_WEIGHT = "mem_cached_weight";
+ public static final String EXTRA_MEM_FREE_WEIGHT = "mem_free_weight";
+ public static final String EXTRA_MEM_ZRAM_WEIGHT = "mem_zram_weight";
+ public static final String EXTRA_MEM_KERNEL_WEIGHT = "mem_kernel_weight";
+ public static final String EXTRA_MEM_NATIVE_WEIGHT = "mem_native_weight";
+ public static final String EXTRA_MEM_TOTAL_WEIGHT = "mem_total_weight";
+ public static final String EXTRA_USE_USS = "use_uss";
+ public static final String EXTRA_TOTAL_TIME = "total_time";
+
+ long[] mMemTimes;
+ double[] mMemStateWeights;
+ double mMemCachedWeight;
+ double mMemFreeWeight;
+ double mMemZRamWeight;
+ double mMemKernelWeight;
+ double mMemNativeWeight;
+ double mMemTotalWeight;
+ boolean mUseUss;
+ long mTotalTime;
+
+ private View mRootView;
+ private ViewGroup mMemStateParent;
+ private ViewGroup mMemUseParent;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+ final Bundle args = getArguments();
+ mMemTimes = args.getLongArray(EXTRA_MEM_TIMES);
+ mMemStateWeights = args.getDoubleArray(EXTRA_MEM_STATE_WEIGHTS);
+ mMemCachedWeight = args.getDouble(EXTRA_MEM_CACHED_WEIGHT);
+ mMemFreeWeight = args.getDouble(EXTRA_MEM_FREE_WEIGHT);
+ mMemZRamWeight = args.getDouble(EXTRA_MEM_ZRAM_WEIGHT);
+ mMemKernelWeight = args.getDouble(EXTRA_MEM_KERNEL_WEIGHT);
+ mMemNativeWeight = args.getDouble(EXTRA_MEM_NATIVE_WEIGHT);
+ mMemTotalWeight = args.getDouble(EXTRA_MEM_TOTAL_WEIGHT);
+ mUseUss = args.getBoolean(EXTRA_USE_USS);
+ mTotalTime = args.getLong(EXTRA_TOTAL_TIME);
+ }
+
+ @Override
+ public View onCreateView(
+ LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ final View view = inflater.inflate(R.layout.process_stats_mem_details, container, false);
+ prepareCustomPreferencesList(container, view, view, false);
+
+ mRootView = view;
+ createDetails();
+ return view;
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ }
+
+ private void createDetails() {
+ mMemStateParent = (ViewGroup)mRootView.findViewById(R.id.mem_state);
+ mMemUseParent = (ViewGroup)mRootView.findViewById(R.id.mem_use);
+
+ fillMemStateSection();
+ fillMemUseSection();
+ }
+
+ private void addDetailsItem(ViewGroup parent, CharSequence title,
+ float level, CharSequence value) {
+ LayoutInflater inflater = getActivity().getLayoutInflater();
+ ViewGroup item = (ViewGroup) inflater.inflate(R.layout.app_percentage_item,
+ null);
+ parent.addView(item);
+ item.findViewById(android.R.id.icon).setVisibility(View.GONE);
+ TextView titleView = (TextView) item.findViewById(android.R.id.title);
+ TextView valueView = (TextView) item.findViewById(android.R.id.text1);
+ titleView.setText(title);
+ valueView.setText(value);
+ ProgressBar progress = (ProgressBar) item.findViewById(android.R.id.progress);
+ progress.setProgress(Math.round(level*100));
+ }
+
+ private void fillMemStateSection() {
+ CharSequence[] labels = getResources().getTextArray(R.array.proc_stats_memory_states);
+ for (int i=0; i<ProcessStats.ADJ_MEM_FACTOR_COUNT; i++) {
+ if (mMemTimes[i] > 0) {
+ float level = ((float)mMemTimes[i])/mTotalTime;
+ addDetailsItem(mMemStateParent, labels[i], level,
+ Formatter.formatShortElapsedTime(getActivity(), mMemTimes[i]));
+ }
+ }
+ }
+
+ private void addMemUseDetailsItem(ViewGroup parent, CharSequence title, double weight) {
+ if (weight > 0) {
+ float level = (float)(weight/mMemTotalWeight);
+ String value = Formatter.formatShortFileSize(getActivity(),
+ (long)((weight * 1024) / mTotalTime));
+ addDetailsItem(parent, title, level, value);
+ }
+ }
+
+ private void fillMemUseSection() {
+ CharSequence[] labels = getResources().getTextArray(R.array.proc_stats_process_states);
+ addMemUseDetailsItem(mMemUseParent,
+ getResources().getText(R.string.mem_use_kernel_type), mMemKernelWeight);
+ addMemUseDetailsItem(mMemUseParent,
+ getResources().getText(R.string.mem_use_native_type), mMemNativeWeight);
+ for (int i=0; i<ProcessStats.STATE_COUNT; i++) {
+ addMemUseDetailsItem(mMemUseParent, labels[i], mMemStateWeights[i]);
+ }
+ addMemUseDetailsItem(mMemUseParent,
+ getResources().getText(R.string.mem_use_kernel_cache_type), mMemCachedWeight);
+ addMemUseDetailsItem(mMemUseParent,
+ getResources().getText(R.string.mem_use_zram_type), mMemZRamWeight);
+ addMemUseDetailsItem(mMemUseParent,
+ getResources().getText(R.string.mem_use_free_type), mMemFreeWeight);
+ addMemUseDetailsItem(mMemUseParent,
+ getResources().getText(R.string.mem_use_total), mMemTotalWeight);
+ }
+}
long mMaxWeight;
long mTotalTime;
+ long[] mMemTimes = new long[ProcessStats.ADJ_MEM_FACTOR_COUNT];
+ double[] mMemStateWeights = new double[ProcessStats.STATE_COUNT];
+ double mMemCachedWeight;
+ double mMemFreeWeight;
+ double mMemZRamWeight;
+ double mMemKernelWeight;
+ double mMemNativeWeight;
+ double mMemTotalWeight;
+
// The actual duration value to use for each duration option. Note these
// are lower than the actual duration, since our durations are computed in
// batches of 3 hours so we want to allow the time we use to be slightly
@Override
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {
+ if (preference instanceof LinearColorPreference) {
+ Bundle args = new Bundle();
+ args.putLongArray(ProcessStatsMemDetail.EXTRA_MEM_TIMES, mMemTimes);
+ args.putDoubleArray(ProcessStatsMemDetail.EXTRA_MEM_STATE_WEIGHTS, mMemStateWeights);
+ args.putDouble(ProcessStatsMemDetail.EXTRA_MEM_CACHED_WEIGHT, mMemCachedWeight);
+ args.putDouble(ProcessStatsMemDetail.EXTRA_MEM_FREE_WEIGHT, mMemFreeWeight);
+ args.putDouble(ProcessStatsMemDetail.EXTRA_MEM_ZRAM_WEIGHT, mMemZRamWeight);
+ args.putDouble(ProcessStatsMemDetail.EXTRA_MEM_KERNEL_WEIGHT, mMemKernelWeight);
+ args.putDouble(ProcessStatsMemDetail.EXTRA_MEM_NATIVE_WEIGHT, mMemNativeWeight);
+ args.putDouble(ProcessStatsMemDetail.EXTRA_MEM_TOTAL_WEIGHT, mMemTotalWeight);
+ args.putBoolean(ProcessStatsMemDetail.EXTRA_USE_USS, mUseUss);
+ args.putLong(ProcessStatsMemDetail.EXTRA_TOTAL_TIME, mTotalTime);
+ ((SettingsActivity) getActivity()).startPreferencePanel(
+ ProcessStatsMemDetail.class.getName(), args, R.string.mem_details_title,
+ null, null, 0);
+ return true;
+ }
+
if (!(preference instanceof ProcessStatsPreference)) {
return false;
}
mStats.mMemFactor, mStats.mStartTime, now);
if (DEBUG) Log.d(TAG, "Total time of stats: " + makeDuration(mTotalTime));
- long[] memTimes = new long[ProcessStats.ADJ_MEM_FACTOR_COUNT];
+ for (int i=0; i<mMemTimes.length; i++) {
+ mMemTimes[i] = 0;
+ }
for (int iscreen=0; iscreen<ProcessStats.ADJ_COUNT; iscreen+=ProcessStats.ADJ_SCREEN_MOD) {
for (int imem=0; imem<ProcessStats.ADJ_MEM_FACTOR_COUNT; imem++) {
int state = imem+iscreen;
- memTimes[imem] += mStats.mMemFactorDurations[state];
+ mMemTimes[imem] += mStats.mMemFactorDurations[state];
}
}
LinearColorPreference colors = new LinearColorPreference(getActivity());
colors.setOrder(-1);
- colors.setOnRegionTappedListener(this);
switch (mMemRegion) {
case LinearColorBar.REGION_RED:
- colors.setColoredRegions(LinearColorBar.REGION_RED);
- memTotalTime = memTimes[ProcessStats.ADJ_MEM_FACTOR_CRITICAL];
+ memTotalTime = mMemTimes[ProcessStats.ADJ_MEM_FACTOR_CRITICAL];
memStates = RED_MEM_STATES;
break;
case LinearColorBar.REGION_YELLOW:
- colors.setColoredRegions(LinearColorBar.REGION_RED
- | LinearColorBar.REGION_YELLOW);
- memTotalTime = memTimes[ProcessStats.ADJ_MEM_FACTOR_CRITICAL]
- + memTimes[ProcessStats.ADJ_MEM_FACTOR_LOW]
- + memTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE];
+ memTotalTime = mMemTimes[ProcessStats.ADJ_MEM_FACTOR_CRITICAL]
+ + mMemTimes[ProcessStats.ADJ_MEM_FACTOR_LOW]
+ + mMemTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE];
memStates = YELLOW_MEM_STATES;
break;
default:
- colors.setColoredRegions(LinearColorBar.REGION_ALL);
memTotalTime = mTotalTime;
memStates = ProcessStats.ALL_MEM_ADJ;
break;
}
- colors.setRatios(memTimes[ProcessStats.ADJ_MEM_FACTOR_CRITICAL] / (float)mTotalTime,
- (memTimes[ProcessStats.ADJ_MEM_FACTOR_LOW]
- + memTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE]) / (float)mTotalTime,
- memTimes[ProcessStats.ADJ_MEM_FACTOR_NORMAL] / (float)mTotalTime);
+ colors.setColoredRegions(LinearColorBar.REGION_RED);
+
+ // Compute memory badness for chart color.
+ int[] badColors = com.android.settings.Utils.BADNESS_COLORS;
+ long timeGood = mMemTimes[ProcessStats.ADJ_MEM_FACTOR_NORMAL];
+ timeGood += (mMemTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE]*2)/3;
+ timeGood += mMemTimes[ProcessStats.ADJ_MEM_FACTOR_LOW]/3;
+ float memBadness = ((float)timeGood)/mTotalTime;
+ int badnessColor = badColors[1 + Math.round(memBadness*(badColors.length-2))];
+ colors.setColors(badnessColor, badnessColor, badnessColor);
+
+ ProcessStats.TotalMemoryUseCollection totalMem = new ProcessStats.TotalMemoryUseCollection(
+ ProcessStats.ALL_SCREEN_ADJ, memStates);
+ mStats.computeTotalMemoryUse(totalMem, now);
+ double freeWeight = totalMem.sysMemFreeWeight + totalMem.sysMemCachedWeight;
+ double usedWeight = totalMem.sysMemKernelWeight + totalMem.sysMemKernelWeight
+ + totalMem.sysMemZRamWeight;
+ mMemCachedWeight = totalMem.sysMemCachedWeight;
+ mMemFreeWeight = totalMem.sysMemFreeWeight;
+ mMemZRamWeight = totalMem.sysMemZRamWeight;
+ mMemKernelWeight = totalMem.sysMemKernelWeight;
+ mMemNativeWeight = totalMem.sysMemNativeWeight;
+ for (int i=0; i<ProcessStats.STATE_COUNT; i++) {
+ if (i == ProcessStats.STATE_SERVICE_RESTARTING) {
+ // These don't really run.
+ mMemStateWeights[i] = 0;
+ } else {
+ mMemStateWeights[i] = totalMem.processStateWeight[i];
+ if (i >= ProcessStats.STATE_HOME) {
+ freeWeight += totalMem.processStateWeight[i];
+ } else {
+ usedWeight += totalMem.processStateWeight[i];
+ }
+ }
+ }
+ mMemTotalWeight = freeWeight + usedWeight;
+ float usedRatio = (float)(usedWeight/(freeWeight+usedWeight));
+ colors.setRatios(usedRatio, 0, 1-usedRatio);
+
+ if (false) {
+ colors.setOnRegionTappedListener(this);
+ switch (mMemRegion) {
+ case LinearColorBar.REGION_RED:
+ colors.setColoredRegions(LinearColorBar.REGION_RED);
+ memTotalTime = mMemTimes[ProcessStats.ADJ_MEM_FACTOR_CRITICAL];
+ memStates = RED_MEM_STATES;
+ break;
+ case LinearColorBar.REGION_YELLOW:
+ colors.setColoredRegions(LinearColorBar.REGION_RED
+ | LinearColorBar.REGION_YELLOW);
+ memTotalTime = mMemTimes[ProcessStats.ADJ_MEM_FACTOR_CRITICAL]
+ + mMemTimes[ProcessStats.ADJ_MEM_FACTOR_LOW]
+ + mMemTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE];
+ memStates = YELLOW_MEM_STATES;
+ break;
+ default:
+ colors.setColoredRegions(LinearColorBar.REGION_ALL);
+ memTotalTime = mTotalTime;
+ memStates = ProcessStats.ALL_MEM_ADJ;
+ break;
+ }
+ colors.setRatios(mMemTimes[ProcessStats.ADJ_MEM_FACTOR_CRITICAL] / (float)mTotalTime,
+ (mMemTimes[ProcessStats.ADJ_MEM_FACTOR_LOW]
+ + mMemTimes[ProcessStats.ADJ_MEM_FACTOR_MODERATE]) / (float)mTotalTime,
+ mMemTimes[ProcessStats.ADJ_MEM_FACTOR_NORMAL] / (float)mTotalTime);
+ }
+
mAppListGroup.addPreference(colors);
ProcessStats.ProcessDataCollection totals = new ProcessStats.ProcessDataCollection(
mGpsOnPaint.setStyle(Paint.Style.STROKE);
mWifiRunningPaint.setStyle(Paint.Style.STROKE);
mCpuRunningPaint.setStyle(Paint.Style.STROKE);
- mPhoneSignalChart.setColors(new int[] {
- 0x00000000, 0xffc43828, 0xffe54918, 0xfff47b00,
- 0xfffabf2c, 0xff679e37, 0xff0a7f42
- });
+ mPhoneSignalChart.setColors(com.android.settings.Utils.BADNESS_COLORS);
mDebugRectPaint.setARGB(255, 255, 0, 0);
mDebugRectPaint.setStyle(Paint.Style.STROKE);
mScreenOnPaint.setColor(0xFF009688);