Merge "Hide Memory usage UI fields if flag is enabled" into main

This commit is contained in:
Kevin Jeon
2023-12-22 17:39:09 +00:00
committed by Android (Google) Code Review
6 changed files with 222 additions and 45 deletions

View File

@@ -9482,6 +9482,13 @@
other {# apps used memory in the last {time}} other {# apps used memory in the last {time}}
}</string> }</string>
<!-- Label for toggle that enables the profiling/aggregating of memory usage [CHAR LIMIT=40]-->
<string name="force_enable_pss_profiling_title">Enable memory usage profiling</string>
<!-- Description with an explanation of the extra resources used if profiling of memory usage is enabled [CHAR LIMIT=NONE]-->
<string name="force_enable_pss_profiling_summary">Memory usage profiling requires additional system resources.</string>
<!-- Summary that shows the current memory usage profiling status as disabled. [CHAR LIMIT=NONE]-->
<string name="pss_profiling_disabled">Memory profiling disabled</string>
<!-- Label for frequency that the app is runnig (e.g. always, sometimes, etc.) [CHAR LIMIT=25] --> <!-- Label for frequency that the app is runnig (e.g. always, sometimes, etc.) [CHAR LIMIT=25] -->
<string name="running_frequency">Frequency</string> <string name="running_frequency">Frequency</string>

View File

@@ -19,45 +19,52 @@
android:title="@string/app_memory_use" android:title="@string/app_memory_use"
android:key="app_list"> android:key="app_list">
<SwitchPreference
android:key="force_enable_pss_profiling"
android:title="@string/force_enable_pss_profiling_title"
android:summary="@string/force_enable_pss_profiling_summary" />
<PreferenceCategory <PreferenceCategory
android:title="@string/average_memory_use"/> android:title="@string/average_memory_use"
android:key="memory_info">
<com.android.settings.SummaryPreference <com.android.settings.SummaryPreference
android:key="status_header" android:key="status_header"
android:selectable="false" /> android:selectable="false" />
<com.android.settings.applications.SpacePreference <com.android.settings.applications.SpacePreference
android:layout_height="5dp" /> android:layout_height="5dp" />
<Preference <Preference
android:key="performance" android:key="performance"
android:selectable="false" android:selectable="false"
android:layout="@layout/horizontal_preference" android:layout="@layout/horizontal_preference"
android:title="@string/memory_performance" /> android:title="@string/memory_performance" />
<Preference <Preference
android:key="total_memory" android:key="total_memory"
android:selectable="false" android:selectable="false"
android:layout="@layout/horizontal_preference" android:layout="@layout/horizontal_preference"
android:title="@string/total_memory" /> android:title="@string/total_memory" />
<Preference <Preference
android:key="average_used" android:key="average_used"
android:selectable="false" android:selectable="false"
android:layout="@layout/horizontal_preference" android:layout="@layout/horizontal_preference"
android:title="@string/average_used" /> android:title="@string/average_used" />
<Preference <Preference
android:key="free" android:key="free"
android:selectable="false" android:selectable="false"
android:layout="@layout/horizontal_preference" android:layout="@layout/horizontal_preference"
android:title="@string/free_memory" /> android:title="@string/free_memory" />
<com.android.settings.applications.SpacePreference <com.android.settings.applications.SpacePreference
android:layout_height="15dp" /> android:layout_height="15dp" />
<Preference <Preference
android:key="apps_list" android:key="apps_list"
android:title="@string/memory_usage_apps" /> android:title="@string/memory_usage_apps" />
</PreferenceCategory>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -16,20 +16,26 @@
package com.android.settings.applications; package com.android.settings.applications;
import android.app.settings.SettingsEnums; import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.icu.text.MessageFormat; import android.icu.text.MessageFormat;
import android.os.Bundle; import android.os.Bundle;
import android.os.Flags;
import android.provider.Settings;
import android.text.format.Formatter; import android.text.format.Formatter;
import android.text.format.Formatter.BytesResult; import android.text.format.Formatter.BytesResult;
import androidx.preference.Preference; import androidx.preference.Preference;
import androidx.preference.Preference.OnPreferenceClickListener; import androidx.preference.Preference.OnPreferenceClickListener;
import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreference;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SummaryPreference; import com.android.settings.SummaryPreference;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.applications.ProcStatsData.MemInfo; import com.android.settings.applications.ProcStatsData.MemInfo;
import com.android.settings.core.SubSettingLauncher; import com.android.settings.core.SubSettingLauncher;
import com.android.settings.development.DisableDevSettingsDialogFragment;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
@@ -37,6 +43,8 @@ import java.util.Map;
public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenceClickListener { public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenceClickListener {
private static final String KEY_PREF_SCREEN = "app_list";
private static final String KEY_MEMORY_INFO_PREF_GROUP = "memory_info";
private static final String KEY_STATUS_HEADER = "status_header"; private static final String KEY_STATUS_HEADER = "status_header";
private static final String KEY_PERFORMANCE = "performance"; private static final String KEY_PERFORMANCE = "performance";
@@ -44,7 +52,9 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc
private static final String KEY_AVERAGY_USED = "average_used"; private static final String KEY_AVERAGY_USED = "average_used";
private static final String KEY_FREE = "free"; private static final String KEY_FREE = "free";
private static final String KEY_APP_LIST = "apps_list"; private static final String KEY_APP_LIST = "apps_list";
private static final String KEY_FORCE_ENABLE_PSS_PROFILING = "force_enable_pss_profiling";
private PreferenceCategory mMemoryInfoPrefCategory;
private SummaryPreference mSummaryPref; private SummaryPreference mSummaryPref;
private Preference mPerformance; private Preference mPerformance;
@@ -52,12 +62,14 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc
private Preference mAverageUsed; private Preference mAverageUsed;
private Preference mFree; private Preference mFree;
private Preference mAppListPreference; private Preference mAppListPreference;
private SwitchPreference mForceEnablePssProfiling;
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
super.onCreate(icicle); super.onCreate(icicle);
addPreferencesFromResource(R.xml.process_stats_summary); addPreferencesFromResource(R.xml.process_stats_summary);
mMemoryInfoPrefCategory = (PreferenceCategory) findPreference(KEY_MEMORY_INFO_PREF_GROUP);
mSummaryPref = (SummaryPreference) findPreference(KEY_STATUS_HEADER); mSummaryPref = (SummaryPreference) findPreference(KEY_STATUS_HEADER);
mPerformance = findPreference(KEY_PERFORMANCE); mPerformance = findPreference(KEY_PERFORMANCE);
mTotalMemory = findPreference(KEY_TOTAL_MEMORY); mTotalMemory = findPreference(KEY_TOTAL_MEMORY);
@@ -65,11 +77,37 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc
mFree = findPreference(KEY_FREE); mFree = findPreference(KEY_FREE);
mAppListPreference = findPreference(KEY_APP_LIST); mAppListPreference = findPreference(KEY_APP_LIST);
mAppListPreference.setOnPreferenceClickListener(this); mAppListPreference.setOnPreferenceClickListener(this);
// This preference is only applicable if the flag for PSS deprecation in AppProfiler is
// enabled. Otherwise, it can immediately be hidden.
mForceEnablePssProfiling =
(SwitchPreference) findPreference(KEY_FORCE_ENABLE_PSS_PROFILING);
if (Flags.removeAppProfilerPssCollection()) {
mForceEnablePssProfiling.setOnPreferenceClickListener(this);
// Make the toggle reflect the current state of the global setting.
mForceEnablePssProfiling.setChecked(isPssProfilingForceEnabled(getContext()));
} else {
mForceEnablePssProfiling.setVisible(false);
}
}
private void refreshPreferences() {
// The memory fields should be static if the flag is not enabled.
if (!Flags.removeAppProfilerPssCollection()) {
return;
}
mMemoryInfoPrefCategory.setVisible(mForceEnablePssProfiling.isChecked());
} }
@Override @Override
public void refreshUi() { public void refreshUi() {
Context context = getContext(); Context context = getContext();
refreshPreferences();
// If PSS collection is not enabled, none of the following work needs to be done.
if (Flags.removeAppProfilerPssCollection() && !isPssProfilingForceEnabled(context)) {
return;
}
MemInfo memInfo = mStatsManager.getMemInfo(); MemInfo memInfo = mStatsManager.getMemInfo();
@@ -100,7 +138,8 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc
String durationString = getString(sDurationLabels[mDurationIndex]); String durationString = getString(sDurationLabels[mDurationIndex]);
int numApps = mStatsManager.getEntries().size(); int numApps = mStatsManager.getEntries().size();
MessageFormat msgFormat = new MessageFormat( MessageFormat msgFormat = new MessageFormat(
getResources().getString(R.string.memory_usage_apps_summary), Locale.getDefault()); getResources().getString(R.string.memory_usage_apps_summary),
Locale.getDefault());
Map<String, Object> arguments = new HashMap<>(); Map<String, Object> arguments = new HashMap<>();
arguments.put("count", numApps); arguments.put("count", numApps);
arguments.put("time", durationString); arguments.put("time", durationString);
@@ -131,7 +170,34 @@ public class ProcessStatsSummary extends ProcessStatsBase implements OnPreferenc
.setSourceMetricsCategory(getMetricsCategory()) .setSourceMetricsCategory(getMetricsCategory())
.launch(); .launch();
return true; return true;
} else if (preference == mForceEnablePssProfiling) {
DisableDevSettingsDialogFragment.show(this);
} }
return false; return false;
} }
private boolean isPssProfilingForceEnabled(Context context) {
ContentResolver cr = context.getContentResolver();
return Settings.Global.getInt(cr, Settings.Global.FORCE_ENABLE_PSS_PROFILING, 0) == 1;
}
/**
* Called when the reboot confirmation button is clicked.
*/
public void onRebootDialogConfirmed() {
Context context = getContext();
ContentResolver cr = context.getContentResolver();
Settings.Global.putInt(cr, Settings.Global.FORCE_ENABLE_PSS_PROFILING,
mForceEnablePssProfiling.isChecked() ? 1 : 0);
refreshPreferences();
}
/**
* Called when the reboot deny button is clicked.
*/
public void onRebootDialogCanceled() {
// Set the toggle to reflect the state of the setting, which should not have changed.
mForceEnablePssProfiling.setChecked(isPssProfilingForceEnabled(getContext()));
}
} }

View File

@@ -29,6 +29,8 @@ import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
import com.android.settings.R; import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.applications.ProcessStatsSummary;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment; import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment
@@ -42,7 +44,7 @@ public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment
return dialog; return dialog;
} }
public static void show(DevelopmentSettingsDashboardFragment host) { public static void show(SettingsPreferenceFragment host) {
final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment(); final DisableDevSettingsDialogFragment dialog = new DisableDevSettingsDialogFragment();
dialog.setTargetFragment(host, 0 /* requestCode */); dialog.setTargetFragment(host, 0 /* requestCode */);
// We need to handle data changes and switch state based on which button user clicks, // We need to handle data changes and switch state based on which button user clicks,
@@ -75,18 +77,31 @@ public class DisableDevSettingsDialogFragment extends InstrumentedDialogFragment
@Override @Override
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
Fragment fragment = getTargetFragment(); Fragment fragment = getTargetFragment();
if (!(fragment instanceof DevelopmentSettingsDashboardFragment)){ if (!(fragment instanceof DevelopmentSettingsDashboardFragment)
&& !(fragment instanceof ProcessStatsSummary)) {
Log.e(TAG, "getTargetFragment return unexpected type"); Log.e(TAG, "getTargetFragment return unexpected type");
} }
final DevelopmentSettingsDashboardFragment host = if (fragment instanceof DevelopmentSettingsDashboardFragment) {
(DevelopmentSettingsDashboardFragment) fragment; final DevelopmentSettingsDashboardFragment host =
if (which == DialogInterface.BUTTON_POSITIVE) { (DevelopmentSettingsDashboardFragment) fragment;
host.onDisableDevelopmentOptionsConfirmed(); if (which == DialogInterface.BUTTON_POSITIVE) {
PowerManager pm = getContext().getSystemService(PowerManager.class); host.onDisableDevelopmentOptionsConfirmed();
pm.reboot(null); PowerManager pm = getContext().getSystemService(PowerManager.class);
} else { pm.reboot(null);
host.onDisableDevelopmentOptionsRejected(); } else {
host.onDisableDevelopmentOptionsRejected();
}
} else if (fragment instanceof ProcessStatsSummary) {
final ProcessStatsSummary host =
(ProcessStatsSummary) fragment;
if (which == DialogInterface.BUTTON_POSITIVE) {
host.onRebootDialogConfirmed();
PowerManager pm = getContext().getSystemService(PowerManager.class);
pm.reboot(null);
} else {
host.onRebootDialogCanceled();
}
} }
} }
} }

View File

@@ -17,6 +17,8 @@
package com.android.settings.development; package com.android.settings.development;
import android.content.Context; import android.content.Context;
import android.os.Flags;
import android.provider.Settings;
import android.text.format.Formatter; import android.text.format.Formatter;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -65,9 +67,13 @@ public class MemoryUsagePreferenceController extends DeveloperOptionsPreferenceC
(long) memInfo.realUsedRam); (long) memInfo.realUsedRam);
final String totalResult = Formatter.formatShortFileSize(mContext, final String totalResult = Formatter.formatShortFileSize(mContext,
(long) memInfo.realTotalRam); (long) memInfo.realTotalRam);
ThreadUtils.postOnMainThread( boolean displayMemorySummary = !Flags.removeAppProfilerPssCollection();
() -> mPreference.setSummary(mContext.getString(R.string.memory_summary, displayMemorySummary |= Settings.Global.getInt(mContext.getContentResolver(),
usedResult, totalResult))); Settings.Global.FORCE_ENABLE_PSS_PROFILING, 0) == 1;
String summary = displayMemorySummary
? mContext.getString(R.string.memory_summary, usedResult, totalResult)
: mContext.getString(R.string.pss_profiling_disabled);
ThreadUtils.postOnMainThread(() -> mPreference.setSummary(summary));
}); });
} }

View File

@@ -0,0 +1,76 @@
/*
* Copyright (C) 2023 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.ui
import android.os.Flags
import android.platform.test.annotations.RequiresFlagsDisabled
import android.platform.test.annotations.RequiresFlagsEnabled
import android.provider.Settings
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import com.android.settings.ui.testutils.SettingsTestUtils.assertHasTexts
import com.android.settings.ui.testutils.SettingsTestUtils.clickObject
import com.android.settings.ui.testutils.SettingsTestUtils.startMainActivityFromHomeScreen
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
@SmallTest
class MemorySettingsTest {
private val device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
@Before
fun setUp() {
device.startMainActivityFromHomeScreen(Settings.ACTION_DEVICE_INFO_SETTINGS)
device.assertHasTexts(listOf(BUILD_NUMBER))
repeat(7) { // Enable development mode
device.clickObject(By.text(BUILD_NUMBER))
}
device.startMainActivityFromHomeScreen(Settings.ACTION_APPLICATION_DEVELOPMENT_SETTINGS)
device.clickObject(By.text(MEMORY_PAGE))
}
@Test
@RequiresFlagsDisabled(Flags.FLAG_REMOVE_APP_PROFILER_PSS_COLLECTION)
fun memoryPageIfPssFlagDisabled() {
device.assertHasTexts(ON_SCREEN_TEXTS_DEFAULT)
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_REMOVE_APP_PROFILER_PSS_COLLECTION)
fun memoryPageIfPssFlagEnabled() {
device.assertHasTexts(ON_SCREEN_TEXTS_PSS_PROFILING_DISABLED)
}
private companion object {
private const val BUILD_NUMBER = "Build number"
private const val MEMORY_PAGE = "Memory"
val ON_SCREEN_TEXTS_DEFAULT = listOf(
"Performance",
"Total memory",
"Average used (%)",
"Free",
)
val ON_SCREEN_TEXTS_PSS_PROFILING_DISABLED = listOf(
"Enable memory usage profiling",
)
}
}