summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Fabián Kozynski <kozynski@google.com> 2023-12-18 12:02:06 -0500
committer Fabián Kozynski <kozynski@google.com> 2023-12-18 12:03:24 -0500
commit6e69995fec23ab1310fb60d74bf271a229437654 (patch)
treea61c8461529ebf64ce8a9c4f1298de625db2e4e4
parent66d088a29e0e0190334612858b5db2bfc2053288 (diff)
Remove GarbageMonitorModule
This module is not in use as it was providing bad data. Fixes: 237065162 Fixes: 243569195 Test: build Test: atest com.android.systemui.qs Flag: None Change-Id: I6fd106b1aea2cb3733c366c758463d50d8faa0d7
-rw-r--r--packages/SystemUI/res/drawable/ic_memory.xml28
-rw-r--r--packages/SystemUI/res/values/config.xml3
-rw-r--r--packages/SystemUI/res/values/strings.xml4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSHost.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java186
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java617
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitorModule.kt39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java113
12 files changed, 5 insertions, 1020 deletions
diff --git a/packages/SystemUI/res/drawable/ic_memory.xml b/packages/SystemUI/res/drawable/ic_memory.xml
deleted file mode 100644
index ada36c58ff1d..000000000000
--- a/packages/SystemUI/res/drawable/ic_memory.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2018 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.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
- <path
- android:pathData="M16.0,5.0l-8.0,0.0l0.0,14.0l8.0,0.0z"
- android:fillAlpha="0.5"
- android:fillColor="#000000"/>
- <path
- android:pathData="M6,9 L6,7 L4,7 L4,5 L6,5 C6,3.9 6.9,3 8,3 L16,3 C17.1,3 18,3.9 18,5 L20,5 L20,7 L18,7 L18,9 L20,9 L20,11 L18,11 L18,13 L20,13 L20,15 L18,15 L18,17 L20,17 L20,19 L18,19 C18,20.1 17.1,21 16,21 L8,21 C6.9,21 6,20.1 6,19 L4,19 L4,17 L6,17 L6,15 L4,15 L4,13 L6,13 L6,11 L4,11 L4,9 L6,9 Z M16,19 L16,5 L8,5 L8,19 L16,19 Z"
- android:fillColor="#000000"/>
-</vector>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index deed6c8c7f25..bf666fb1b8c2 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -480,9 +480,6 @@
This name is in the ComponentName flattened format (package/class) -->
<string name="config_remoteCopyPackage" translatable="false"></string>
- <!-- On debuggable builds, alert the user if SystemUI PSS goes over this number (in kb) -->
- <integer name="watch_heap_limit">256000</integer>
-
<!-- SystemUI Plugins that can be loaded on user builds. -->
<string-array name="config_pluginAllowlist" translatable="false">
<item>com.android.systemui</item>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index e10925d551e2..f4b25a701825 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2397,10 +2397,6 @@
<!-- URl of the webpage that explains battery saver. -->
<string name="help_uri_battery_saver_learn_more_link_target" translatable="false"></string>
- <!-- Name for a quick settings tile, used only by platform developers, to extract the SystemUI process memory and send it to another
- app for debugging. Will not be seen by users. [CHAR LIMIT=20] -->
- <string name="heap_dump_tile_name">Dump SysUI Heap</string>
-
<!-- Title for the privacy indicators dialog, only appears as part of a11y descriptions [CHAR LIMIT=NONE] -->
<string name="ongoing_privacy_dialog_a11y_title">In use</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
index 1ab64b76b0dc..ba3357c8b591 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSHost.java
@@ -17,12 +17,10 @@ package com.android.systemui.qs;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
-import android.os.Build;
import android.provider.Settings;
-import com.android.systemui.res.R;
import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.util.leak.GarbageMonitor;
+import com.android.systemui.res.R;
import java.util.ArrayList;
import java.util.Arrays;
@@ -44,10 +42,6 @@ public interface QSHost {
final String defaultTileList = res.getString(R.string.quick_settings_tiles_default);
tiles.addAll(Arrays.asList(defaultTileList.split(",")));
- if (Build.IS_DEBUGGABLE
- && GarbageMonitor.ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS) {
- tiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
- }
return tiles;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 2af7ae0614ac..47b062430ca5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -23,7 +23,6 @@ import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
-import android.os.Build;
import android.provider.Settings;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
@@ -33,7 +32,6 @@ import android.widget.Button;
import androidx.annotation.Nullable;
-import com.android.systemui.res.R;
import com.android.systemui.dagger.qualifiers.Background;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.plugins.qs.QSTile;
@@ -42,8 +40,8 @@ import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.dagger.QSScope;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon;
+import com.android.systemui.res.R;
import com.android.systemui.settings.UserTracker;
-import com.android.systemui.util.leak.GarbageMonitor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -114,9 +112,6 @@ public class TileQueryHelper {
possibleTiles.add(spec);
}
}
- if (Build.IS_DEBUGGABLE && !current.contains(GarbageMonitor.MemoryTile.TILE_SPEC)) {
- possibleTiles.add(GarbageMonitor.MemoryTile.TILE_SPEC);
- }
final ArrayList<QSTile> tilesToAdd = new ArrayList<>();
possibleTiles.remove("cell");
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
index 17e6375967fc..bdcbac09a254 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSFactoryImpl.java
@@ -14,7 +14,6 @@
package com.android.systemui.qs.tileimpl;
-import android.os.Build;
import android.util.Log;
import androidx.annotation.Nullable;
@@ -25,15 +24,14 @@ import com.android.systemui.plugins.qs.QSFactory;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.QSHost;
import com.android.systemui.qs.external.CustomTile;
-import com.android.systemui.util.leak.GarbageMonitor;
-
-import dagger.Lazy;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Provider;
+import dagger.Lazy;
+
/**
* A factory that creates Quick Settings tiles based on a tileSpec
*
@@ -79,9 +77,7 @@ public class QSFactoryImpl implements QSFactory {
@Nullable
protected QSTileImpl createTileInternal(String tileSpec) {
// Stock tiles.
- if (mTileMap.containsKey(tileSpec)
- // We should not return a Garbage Monitory Tile if the build is not Debuggable
- && (!tileSpec.equals(GarbageMonitor.MemoryTile.TILE_SPEC) || Build.IS_DEBUGGABLE)) {
+ if (mTileMap.containsKey(tileSpec)) {
return mTileMap.get(tileSpec).get();
}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java b/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
deleted file mode 100644
index 82153600e473..000000000000
--- a/packages/SystemUI/src/com/android/systemui/util/leak/DumpTruck.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (C) 2017 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.systemui.util.leak;
-
-import android.content.ClipData;
-import android.content.ClipDescription;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Build;
-import android.util.Log;
-
-import androidx.core.content.FileProvider;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
-
-/**
- * Utility class for dumping, compressing, sending, and serving heap dump files.
- *
- * <p>Unlike the Internet, this IS a big truck you can dump something on.
- */
-public class DumpTruck {
- private static final String FILEPROVIDER_AUTHORITY = "com.android.systemui.fileprovider";
- private static final String FILEPROVIDER_PATH = "leak";
-
- private static final String TAG = "DumpTruck";
- private static final int BUFSIZ = 1024 * 1024; // 1MB
-
- private final Context context;
- private final GarbageMonitor mGarbageMonitor;
- private Uri hprofUri;
- private long rss;
- final StringBuilder body = new StringBuilder();
-
- public DumpTruck(Context context, GarbageMonitor garbageMonitor) {
- this.context = context;
- mGarbageMonitor = garbageMonitor;
- }
-
- /**
- * Capture memory for the given processes and zip them up for sharing.
- *
- * @param pids
- * @return this, for chaining
- */
- public DumpTruck captureHeaps(List<Long> pids) {
- final File dumpDir = new File(context.getCacheDir(), FILEPROVIDER_PATH);
- dumpDir.mkdirs();
- hprofUri = null;
-
- body.setLength(0);
- body.append("Build: ").append(Build.DISPLAY).append("\n\nProcesses:\n");
-
- final ArrayList<String> paths = new ArrayList<String>();
- final int myPid = android.os.Process.myPid();
-
- for (Long pidL : pids) {
- final int pid = pidL.intValue();
- body.append(" pid ").append(pid);
- GarbageMonitor.ProcessMemInfo info = mGarbageMonitor.getMemInfo(pid);
- if (info != null) {
- body.append(":")
- .append(" up=")
- .append(info.getUptime())
- .append(" rss=")
- .append(info.currentRss);
- rss = info.currentRss;
- }
- if (pid == myPid) {
- final String path =
- new File(dumpDir, String.format("heap-%d.ahprof", pid)).getPath();
- Log.v(TAG, "Dumping memory info for process " + pid + " to " + path);
- try {
- android.os.Debug.dumpHprofData(path); // will block
- paths.add(path);
- body.append(" (hprof attached)");
- } catch (IOException e) {
- Log.e(TAG, "error dumping memory:", e);
- body.append("\n** Could not dump heap: \n").append(e.toString()).append("\n");
- }
- }
- body.append("\n");
- }
-
- try {
- final String zipfile =
- new File(dumpDir, String.format("hprof-%d.zip", System.currentTimeMillis()))
- .getCanonicalPath();
- if (DumpTruck.zipUp(zipfile, paths)) {
- final File pathFile = new File(zipfile);
- hprofUri = FileProvider.getUriForFile(context, FILEPROVIDER_AUTHORITY, pathFile);
- Log.v(TAG, "Heap dump accessible at URI: " + hprofUri);
- }
- } catch (IOException e) {
- Log.e(TAG, "unable to zip up heapdumps", e);
- body.append("\n** Could not zip up files: \n").append(e.toString()).append("\n");
- }
-
- return this;
- }
-
- /**
- * Get the Uri of the current heap dump. Be sure to call captureHeaps first.
- *
- * @return Uri to the dump served by the SystemUI file provider
- */
- public Uri getDumpUri() {
- return hprofUri;
- }
-
- /**
- * Get an ACTION_SEND intent suitable for startActivity() or attaching to a Notification.
- *
- * @return share intent
- */
- public Intent createShareIntent() {
- Intent shareIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
- shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- shareIntent.putExtra(Intent.EXTRA_SUBJECT,
- String.format("SystemUI memory dump (rss=%dM)", rss / 1024));
-
- shareIntent.putExtra(Intent.EXTRA_TEXT, body.toString());
-
- if (hprofUri != null) {
- final ArrayList<Uri> uriList = new ArrayList<>();
- uriList.add(hprofUri);
- shareIntent.setType("application/zip");
- shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uriList);
-
- // Include URI in ClipData also, so that grantPermission picks it up.
- // We don't use setData here because some apps interpret this as "to:".
- ClipData clipdata = new ClipData(new ClipDescription("content",
- new String[]{ClipDescription.MIMETYPE_TEXT_PLAIN}),
- new ClipData.Item(hprofUri));
- shareIntent.setClipData(clipdata);
- shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
- return shareIntent;
- }
-
- private static boolean zipUp(String zipfilePath, ArrayList<String> paths) {
- try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipfilePath))) {
- final byte[] buf = new byte[BUFSIZ];
-
- for (String filename : paths) {
- try (InputStream is = new BufferedInputStream(new FileInputStream(filename))) {
- ZipEntry entry = new ZipEntry(filename);
- zos.putNextEntry(entry);
- int len;
- while (0 < (len = is.read(buf, 0, BUFSIZ))) {
- zos.write(buf, 0, len);
- }
- zos.closeEntry();
- }
- }
- return true;
- } catch (IOException e) {
- Log.e(TAG, "error zipping up profile data", e);
- }
- return false;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
deleted file mode 100644
index de392d3f444f..000000000000
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- * Copyright (C) 2017 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.systemui.util.leak;
-
-import static android.service.quicksettings.Tile.STATE_ACTIVE;
-import static android.telephony.ims.feature.ImsFeature.STATE_UNAVAILABLE;
-
-import static com.android.internal.logging.MetricsLogger.VIEW_UNKNOWN;
-
-import android.annotation.Nullable;
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.ColorFilter;
-import android.graphics.Paint;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Process;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.text.format.DateUtils;
-import android.util.Log;
-import android.util.LongSparseArray;
-import android.view.View;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.CoreStartable;
-import com.android.systemui.Dumpable;
-import com.android.systemui.res.R;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Background;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSHost;
-import com.android.systemui.qs.QsEventLogger;
-import com.android.systemui.qs.logging.QSLogger;
-import com.android.systemui.qs.pipeline.domain.interactor.PanelInteractor;
-import com.android.systemui.qs.tileimpl.QSTileImpl;
-import com.android.systemui.util.concurrency.DelayableExecutor;
-import com.android.systemui.util.concurrency.MessageRouter;
-
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.inject.Inject;
-
-/**
- * Suite of tools to periodically inspect the System UI heap and possibly prompt the user to
- * capture heap dumps and report them. Includes the implementation of the "Dump SysUI Heap"
- * quick settings tile.
- */
-@SysUISingleton
-public class GarbageMonitor implements Dumpable {
- // Feature switches
- // ================
-
- // Whether to use TrackedGarbage to trigger LeakReporter. Off by default unless you set the
- // appropriate sysprop on a userdebug device.
- public static final boolean LEAK_REPORTING_ENABLED = Build.IS_DEBUGGABLE
- && SystemProperties.getBoolean("debug.enable_leak_reporting", false);
- public static final String FORCE_ENABLE_LEAK_REPORTING = "sysui_force_enable_leak_reporting";
-
- // Heap tracking: watch the current memory levels and update the MemoryTile if available.
- // On for all userdebug devices.
- public static final boolean HEAP_TRACKING_ENABLED = Build.IS_DEBUGGABLE;
-
- // Tell QSTileHost.java to toss this into the default tileset?
- public static final boolean ADD_MEMORY_TILE_TO_DEFAULT_ON_DEBUGGABLE_BUILDS = true;
-
- // whether to use ActivityManager.setHeapLimit (and post a notification to the user asking
- // to dump the heap). Off by default unless you set the appropriate sysprop on userdebug
- private static final boolean ENABLE_AM_HEAP_LIMIT = Build.IS_DEBUGGABLE
- && SystemProperties.getBoolean("debug.enable_sysui_heap_limit", false);
-
- // Tuning params
- // =============
-
- // threshold for setHeapLimit(), in KB (overrides R.integer.watch_heap_limit)
- private static final String SETTINGS_KEY_AM_HEAP_LIMIT = "systemui_am_heap_limit";
-
- private static final long GARBAGE_INSPECTION_INTERVAL =
- 15 * DateUtils.MINUTE_IN_MILLIS; // 15 min
- private static final long HEAP_TRACK_INTERVAL = 1 * DateUtils.MINUTE_IN_MILLIS; // 1 min
- private static final int HEAP_TRACK_HISTORY_LEN = 720; // 12 hours
-
- private static final int DO_GARBAGE_INSPECTION = 1000;
- private static final int DO_HEAP_TRACK = 3000;
-
- static final int GARBAGE_ALLOWANCE = 5;
-
- private static final String TAG = "GarbageMonitor";
- private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
- private final MessageRouter mMessageRouter;
- private final TrackedGarbage mTrackedGarbage;
- private final LeakReporter mLeakReporter;
- private final Context mContext;
- private final DelayableExecutor mDelayableExecutor;
- private MemoryTile mQSTile;
- private final DumpTruck mDumpTruck;
-
- private final LongSparseArray<ProcessMemInfo> mData = new LongSparseArray<>();
- private final ArrayList<Long> mPids = new ArrayList<>();
-
- private long mHeapLimit;
-
- /**
- */
- @Inject
- public GarbageMonitor(
- Context context,
- @Background DelayableExecutor delayableExecutor,
- @Background MessageRouter messageRouter,
- LeakDetector leakDetector,
- LeakReporter leakReporter,
- DumpManager dumpManager) {
- mContext = context.getApplicationContext();
-
- mDelayableExecutor = delayableExecutor;
- mMessageRouter = messageRouter;
- mMessageRouter.subscribeTo(DO_GARBAGE_INSPECTION, this::doGarbageInspection);
- mMessageRouter.subscribeTo(DO_HEAP_TRACK, this::doHeapTrack);
-
- mTrackedGarbage = leakDetector.getTrackedGarbage();
- mLeakReporter = leakReporter;
-
- mDumpTruck = new DumpTruck(mContext, this);
-
- dumpManager.registerDumpable(getClass().getSimpleName(), this);
-
- if (ENABLE_AM_HEAP_LIMIT) {
- mHeapLimit = Settings.Global.getInt(context.getContentResolver(),
- SETTINGS_KEY_AM_HEAP_LIMIT,
- mContext.getResources().getInteger(R.integer.watch_heap_limit));
- }
- }
-
- public void startLeakMonitor() {
- if (mTrackedGarbage == null) {
- return;
- }
-
- mMessageRouter.sendMessage(DO_GARBAGE_INSPECTION);
- }
-
- public void startHeapTracking() {
- startTrackingProcess(
- android.os.Process.myPid(), mContext.getPackageName(), System.currentTimeMillis());
- mMessageRouter.sendMessage(DO_HEAP_TRACK);
- }
-
- private boolean gcAndCheckGarbage() {
- if (mTrackedGarbage.countOldGarbage() > GARBAGE_ALLOWANCE) {
- Runtime.getRuntime().gc();
- return true;
- }
- return false;
- }
-
- void reinspectGarbageAfterGc() {
- int count = mTrackedGarbage.countOldGarbage();
- if (count > GARBAGE_ALLOWANCE) {
- mLeakReporter.dumpLeak(count);
- }
- }
-
- public ProcessMemInfo getMemInfo(int pid) {
- return mData.get(pid);
- }
-
- public List<Long> getTrackedProcesses() {
- return mPids;
- }
-
- public void startTrackingProcess(long pid, String name, long start) {
- synchronized (mPids) {
- if (mPids.contains(pid)) return;
-
- mPids.add(pid);
- logPids();
-
- mData.put(pid, new ProcessMemInfo(pid, name, start));
- }
- }
-
- private void logPids() {
- if (DEBUG) {
- StringBuffer sb = new StringBuffer("Now tracking processes: ");
- for (int i = 0; i < mPids.size(); i++) {
- final int p = mPids.get(i).intValue();
- sb.append(" ");
- }
- Log.v(TAG, sb.toString());
- }
- }
-
- private void update() {
- synchronized (mPids) {
- for (int i = 0; i < mPids.size(); i++) {
- final int pid = mPids.get(i).intValue();
- // rssValues contains [VmRSS, RssFile, RssAnon, VmSwap].
- long[] rssValues = Process.getRss(pid);
- if (rssValues == null && rssValues.length == 0) {
- if (DEBUG) Log.e(TAG, "update: Process.getRss() didn't provide any values.");
- break;
- }
- long rss = rssValues[0];
- final ProcessMemInfo info = mData.get(pid);
- info.rss[info.head] = info.currentRss = rss;
- info.head = (info.head + 1) % info.rss.length;
- if (info.currentRss > info.max) info.max = info.currentRss;
- if (info.currentRss == 0) {
- if (DEBUG) Log.v(TAG, "update: pid " + pid + " has rss=0, it probably died");
- mData.remove(pid);
- }
- }
- for (int i = mPids.size() - 1; i >= 0; i--) {
- final long pid = mPids.get(i).intValue();
- if (mData.get(pid) == null) {
- mPids.remove(i);
- logPids();
- }
- }
- }
- if (mQSTile != null) mQSTile.update();
- }
-
- private void setTile(MemoryTile tile) {
- mQSTile = tile;
- if (tile != null) tile.update();
- }
-
- private static String formatBytes(long b) {
- String[] SUFFIXES = {"B", "K", "M", "G", "T"};
- int i;
- for (i = 0; i < SUFFIXES.length; i++) {
- if (b < 1024) break;
- b /= 1024;
- }
- return b + SUFFIXES[i];
- }
-
- private Intent dumpHprofAndGetShareIntent() {
- return mDumpTruck.captureHeaps(getTrackedProcesses()).createShareIntent();
- }
-
- @Override
- public void dump(PrintWriter pw, @Nullable String[] args) {
- pw.println("GarbageMonitor params:");
- pw.println(String.format(" mHeapLimit=%d KB", mHeapLimit));
- pw.println(String.format(" GARBAGE_INSPECTION_INTERVAL=%d (%.1f mins)",
- GARBAGE_INSPECTION_INTERVAL,
- (float) GARBAGE_INSPECTION_INTERVAL / DateUtils.MINUTE_IN_MILLIS));
- final float htiMins = HEAP_TRACK_INTERVAL / DateUtils.MINUTE_IN_MILLIS;
- pw.println(String.format(" HEAP_TRACK_INTERVAL=%d (%.1f mins)",
- HEAP_TRACK_INTERVAL,
- htiMins));
- pw.println(String.format(" HEAP_TRACK_HISTORY_LEN=%d (%.1f hr total)",
- HEAP_TRACK_HISTORY_LEN,
- (float) HEAP_TRACK_HISTORY_LEN * htiMins / 60f));
-
- pw.println("GarbageMonitor tracked processes:");
-
- for (long pid : mPids) {
- final ProcessMemInfo pmi = mData.get(pid);
- if (pmi != null) {
- pmi.dump(pw, args);
- }
- }
- }
-
-
- private static class MemoryIconDrawable extends Drawable {
- long rss, limit;
- final Drawable baseIcon;
- final Paint paint = new Paint();
- final float dp;
-
- MemoryIconDrawable(Context context) {
- baseIcon = context.getDrawable(R.drawable.ic_memory).mutate();
- dp = context.getResources().getDisplayMetrics().density;
- paint.setColor(Color.WHITE);
- }
-
- public void setRss(long rss) {
- if (rss != this.rss) {
- this.rss = rss;
- invalidateSelf();
- }
- }
-
- public void setLimit(long limit) {
- if (limit != this.limit) {
- this.limit = limit;
- invalidateSelf();
- }
- }
-
- @Override
- public void draw(Canvas canvas) {
- baseIcon.draw(canvas);
-
- if (limit > 0 && rss > 0) {
- float frac = Math.min(1f, (float) rss / limit);
-
- final Rect bounds = getBounds();
- canvas.translate(bounds.left + 8 * dp, bounds.top + 5 * dp);
- //android:pathData="M16.0,5.0l-8.0,0.0l0.0,14.0l8.0,0.0z"
- canvas.drawRect(0, 14 * dp * (1 - frac), 8 * dp + 1, 14 * dp + 1, paint);
- }
- }
-
- @Override
- public void setBounds(int left, int top, int right, int bottom) {
- super.setBounds(left, top, right, bottom);
- baseIcon.setBounds(left, top, right, bottom);
- }
-
- @Override
- public int getIntrinsicHeight() {
- return baseIcon.getIntrinsicHeight();
- }
-
- @Override
- public int getIntrinsicWidth() {
- return baseIcon.getIntrinsicWidth();
- }
-
- @Override
- public void setAlpha(int i) {
- baseIcon.setAlpha(i);
- }
-
- @Override
- public void setColorFilter(ColorFilter colorFilter) {
- baseIcon.setColorFilter(colorFilter);
- paint.setColorFilter(colorFilter);
- }
-
- @Override
- public void setTint(int tint) {
- super.setTint(tint);
- baseIcon.setTint(tint);
- }
-
- @Override
- public void setTintList(ColorStateList tint) {
- super.setTintList(tint);
- baseIcon.setTintList(tint);
- }
-
- @Override
- public void setTintMode(PorterDuff.Mode tintMode) {
- super.setTintMode(tintMode);
- baseIcon.setTintMode(tintMode);
- }
-
- @Override
- public int getOpacity() {
- return PixelFormat.TRANSLUCENT;
- }
- }
-
- private static class MemoryGraphIcon extends QSTile.Icon {
- long rss, limit;
-
- public void setRss(long rss) {
- this.rss = rss;
- }
-
- public void setHeapLimit(long limit) {
- this.limit = limit;
- }
-
- @Override
- public Drawable getDrawable(Context context) {
- final MemoryIconDrawable drawable = new MemoryIconDrawable(context);
- drawable.setRss(rss);
- drawable.setLimit(limit);
- return drawable;
- }
- }
-
- public static class MemoryTile extends QSTileImpl<QSTile.State> {
- public static final String TILE_SPEC = "dbg:mem";
-
- private final GarbageMonitor gm;
- private ProcessMemInfo pmi;
- private boolean dumpInProgress;
- private final PanelInteractor mPanelInteractor;
-
- @Inject
- public MemoryTile(
- QSHost host,
- QsEventLogger uiEventLogger,
- @Background Looper backgroundLooper,
- @Main Handler mainHandler,
- FalsingManager falsingManager,
- MetricsLogger metricsLogger,
- StatusBarStateController statusBarStateController,
- ActivityStarter activityStarter,
- QSLogger qsLogger,
- GarbageMonitor monitor,
- PanelInteractor panelInteractor
- ) {
- super(host, uiEventLogger, backgroundLooper, mainHandler, falsingManager, metricsLogger,
- statusBarStateController, activityStarter, qsLogger);
- gm = monitor;
- mPanelInteractor = panelInteractor;
- }
-
- @Override
- public State newTileState() {
- return new QSTile.State();
- }
-
- @Override
- public Intent getLongClickIntent() {
- return new Intent();
- }
-
- @Override
- protected void handleClick(@Nullable View view) {
- if (dumpInProgress) return;
-
- dumpInProgress = true;
- refreshState();
- new Thread("HeapDumpThread") {
- @Override
- public void run() {
- try {
- // wait for animations & state changes
- Thread.sleep(500);
- } catch (InterruptedException ignored) { }
- final Intent shareIntent = gm.dumpHprofAndGetShareIntent();
- mHandler.post(() -> {
- dumpInProgress = false;
- refreshState();
- mPanelInteractor.collapsePanels();
- mActivityStarter.postStartActivityDismissingKeyguard(shareIntent, 0);
- });
- }
- }.start();
- }
-
- @Override
- public int getMetricsCategory() {
- return VIEW_UNKNOWN;
- }
-
- @Override
- public void handleSetListening(boolean listening) {
- super.handleSetListening(listening);
- if (gm != null) gm.setTile(listening ? this : null);
-
- final ActivityManager am = mContext.getSystemService(ActivityManager.class);
- if (listening && gm.mHeapLimit > 0) {
- am.setWatchHeapLimit(1024 * gm.mHeapLimit); // why is this in bytes?
- } else {
- am.clearWatchHeapLimit();
- }
- }
-
- @Override
- public CharSequence getTileLabel() {
- return getState().label;
- }
-
- @Override
- protected void handleUpdateState(State state, Object arg) {
- pmi = gm.getMemInfo(Process.myPid());
- final MemoryGraphIcon icon = new MemoryGraphIcon();
- icon.setHeapLimit(gm.mHeapLimit);
- state.state = dumpInProgress ? STATE_UNAVAILABLE : STATE_ACTIVE;
- state.label = dumpInProgress
- ? "Dumping..."
- : mContext.getString(R.string.heap_dump_tile_name);
- if (pmi != null) {
- icon.setRss(pmi.currentRss);
- state.secondaryLabel =
- String.format(
- "rss: %s / %s",
- formatBytes(pmi.currentRss * 1024),
- formatBytes(gm.mHeapLimit * 1024));
- } else {
- icon.setRss(0);
- state.secondaryLabel = null;
- }
- state.icon = icon;
- }
-
- public void update() {
- refreshState();
- }
-
- public long getRss() {
- return pmi != null ? pmi.currentRss : 0;
- }
-
- public long getHeapLimit() {
- return gm != null ? gm.mHeapLimit : 0;
- }
- }
-
- /** */
- public static class ProcessMemInfo implements Dumpable {
- public long pid;
- public String name;
- public long startTime;
- public long currentRss;
- public long[] rss = new long[HEAP_TRACK_HISTORY_LEN];
- public long max = 1;
- public int head = 0;
-
- public ProcessMemInfo(long pid, String name, long start) {
- this.pid = pid;
- this.name = name;
- this.startTime = start;
- }
-
- public long getUptime() {
- return System.currentTimeMillis() - startTime;
- }
-
- @Override
- public void dump(PrintWriter pw, @Nullable String[] args) {
- pw.print("{ \"pid\": ");
- pw.print(pid);
- pw.print(", \"name\": \"");
- pw.print(name.replace('"', '-'));
- pw.print("\", \"start\": ");
- pw.print(startTime);
- pw.print(", \"rss\": [");
- // write rss values starting from the oldest, which is rss[head], wrapping around to
- // rss[(head-1) % rss.length]
- for (int i = 0; i < rss.length; i++) {
- if (i > 0) pw.print(",");
- pw.print(rss[(head + i) % rss.length]);
- }
- pw.println("] }");
- }
- }
-
- /** */
- @SysUISingleton
- public static class Service implements CoreStartable, Dumpable {
- private final Context mContext;
- private final GarbageMonitor mGarbageMonitor;
-
- @Inject
- public Service(Context context, GarbageMonitor garbageMonitor) {
- mContext = context;
- mGarbageMonitor = garbageMonitor;
- }
-
- @Override
- public void start() {
- boolean forceEnable =
- Settings.Secure.getInt(
- mContext.getContentResolver(), FORCE_ENABLE_LEAK_REPORTING, 0)
- != 0;
- if (LEAK_REPORTING_ENABLED || forceEnable) {
- mGarbageMonitor.startLeakMonitor();
- }
- if (HEAP_TRACKING_ENABLED || forceEnable) {
- mGarbageMonitor.startHeapTracking();
- }
- }
-
- @Override
- public void dump(PrintWriter pw, @Nullable String[] args) {
- if (mGarbageMonitor != null) mGarbageMonitor.dump(pw, args);
- }
- }
-
- private void doGarbageInspection(int id) {
- if (gcAndCheckGarbage()) {
- mDelayableExecutor.executeDelayed(this::reinspectGarbageAfterGc, 100);
- }
-
- mMessageRouter.cancelMessages(DO_GARBAGE_INSPECTION);
- mMessageRouter.sendMessageDelayed(DO_GARBAGE_INSPECTION, GARBAGE_INSPECTION_INTERVAL);
- }
-
- private void doHeapTrack(int id) {
- update();
- mMessageRouter.cancelMessages(DO_HEAP_TRACK);
- mMessageRouter.sendMessageDelayed(DO_HEAP_TRACK, HEAP_TRACK_INTERVAL);
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitorModule.kt b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitorModule.kt
deleted file mode 100644
index e975200e4d52..000000000000
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitorModule.kt
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2021 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.systemui.util.leak
-
-import com.android.systemui.CoreStartable
-import com.android.systemui.qs.tileimpl.QSTileImpl
-import dagger.Binds
-import dagger.Module
-import dagger.multibindings.ClassKey
-import dagger.multibindings.IntoMap
-import dagger.multibindings.StringKey
-
-@Module
-interface GarbageMonitorModule {
- /** Inject into GarbageMonitor.Service. */
- @Binds
- @IntoMap
- @ClassKey(GarbageMonitor::class)
- fun bindGarbageMonitorService(sysui: GarbageMonitor.Service): CoreStartable
-
- @Binds
- @IntoMap
- @StringKey(GarbageMonitor.MemoryTile.TILE_SPEC)
- fun bindMemoryTile(memoryTile: GarbageMonitor.MemoryTile): QSTileImpl<*>
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index 5e2423a8b373..ef7798e545d3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -447,10 +447,6 @@ public class QSTileHostTest extends SysuiTestCase {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles_default, "spec1,spec1");
List<String> specs = QSTileHost.loadTileSpecs(mContext, "default");
-
- // Remove spurious tiles, like dbg:mem
- specs.removeIf(spec -> !"spec1".equals(spec));
- assertEquals(1, specs.size());
}
@Test
@@ -458,10 +454,6 @@ public class QSTileHostTest extends SysuiTestCase {
mContext.getOrCreateTestableResources()
.addOverride(R.string.quick_settings_tiles_default, "spec1");
List<String> specs = QSTileHost.loadTileSpecs(mContext, "default,spec1");
-
- // Remove spurious tiles, like dbg:mem
- specs.removeIf(spec -> !"spec1".equals(spec));
- assertEquals(1, specs.size());
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
index 067218a9c983..5201e5d9ccf7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tileimpl/QSFactoryImplTest.kt
@@ -50,7 +50,6 @@ import com.android.systemui.qs.tiles.RotationLockTile
import com.android.systemui.qs.tiles.ScreenRecordTile
import com.android.systemui.qs.tiles.UiModeNightTile
import com.android.systemui.qs.tiles.WorkModeTile
-import com.android.systemui.util.leak.GarbageMonitor
import com.android.systemui.util.mockito.any
import com.google.common.truth.Truth.assertThat
import org.junit.Before
@@ -117,7 +116,6 @@ class QSFactoryImplTest : SysuiTestCase() {
@Mock private lateinit var dataSaverTile: DataSaverTile
@Mock private lateinit var nightDisplayTile: NightDisplayTile
@Mock private lateinit var nfcTile: NfcTile
- @Mock private lateinit var memoryTile: GarbageMonitor.MemoryTile
@Mock private lateinit var darkModeTile: UiModeNightTile
@Mock private lateinit var screenRecordTile: ScreenRecordTile
@Mock private lateinit var reduceBrightColorsTile: ReduceBrightColorsTile
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java
deleted file mode 100644
index a2b016f22473..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/util/leak/GarbageMonitorTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright (C) 2017 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.systemui.util.leak;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.testing.AndroidTestingRunner;
-
-import androidx.test.filters.SmallTest;
-
-import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dump.DumpManager;
-import com.android.systemui.util.concurrency.FakeExecutor;
-import com.android.systemui.util.concurrency.MessageRouterImpl;
-import com.android.systemui.util.time.FakeSystemClock;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-@SmallTest
-@RunWith(AndroidTestingRunner.class)
-public class GarbageMonitorTest extends SysuiTestCase {
-
- @Mock private LeakReporter mLeakReporter;
- @Mock private TrackedGarbage mTrackedGarbage;
- @Mock private DumpManager mDumpManager;
- private GarbageMonitor mGarbageMonitor;
- private final FakeExecutor mFakeExecutor = new FakeExecutor(new FakeSystemClock());
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mGarbageMonitor =
- new GarbageMonitor(
- mContext,
- mFakeExecutor,
- new MessageRouterImpl(mFakeExecutor),
- new LeakDetector(null, mTrackedGarbage, null, mDumpManager),
- mLeakReporter,
- mDumpManager);
- }
-
- @Test
- public void testALittleGarbage_doesntDump() {
- when(mTrackedGarbage.countOldGarbage()).thenReturn(GarbageMonitor.GARBAGE_ALLOWANCE);
-
- mGarbageMonitor.reinspectGarbageAfterGc();
-
- verify(mLeakReporter, never()).dumpLeak(anyInt());
- }
-
- @Test
- public void testTransientGarbage_doesntDump() {
- when(mTrackedGarbage.countOldGarbage()).thenReturn(GarbageMonitor.GARBAGE_ALLOWANCE + 1);
-
- // Start the leak monitor. Nothing gets reported immediately.
- mGarbageMonitor.startLeakMonitor();
- mFakeExecutor.runAllReady();
- verify(mLeakReporter, never()).dumpLeak(anyInt());
-
- // Garbage gets reset to 0 before the leak reporte actually gets called.
- when(mTrackedGarbage.countOldGarbage()).thenReturn(0);
- mFakeExecutor.advanceClockToLast();
- mFakeExecutor.runAllReady();
-
- // Therefore nothing gets dumped.
- verify(mLeakReporter, never()).dumpLeak(anyInt());
- }
-
- @Test
- public void testLotsOfPersistentGarbage_dumps() {
- when(mTrackedGarbage.countOldGarbage()).thenReturn(GarbageMonitor.GARBAGE_ALLOWANCE + 1);
-
- mGarbageMonitor.reinspectGarbageAfterGc();
-
- verify(mLeakReporter).dumpLeak(GarbageMonitor.GARBAGE_ALLOWANCE + 1);
- }
-
- @Test
- public void testLotsOfPersistentGarbage_dumpsAfterAtime() {
- when(mTrackedGarbage.countOldGarbage()).thenReturn(GarbageMonitor.GARBAGE_ALLOWANCE + 1);
-
- // Start the leak monitor. Nothing gets reported immediately.
- mGarbageMonitor.startLeakMonitor();
- mFakeExecutor.runAllReady();
- verify(mLeakReporter, never()).dumpLeak(anyInt());
-
- mFakeExecutor.advanceClockToLast();
- mFakeExecutor.runAllReady();
-
- verify(mLeakReporter).dumpLeak(GarbageMonitor.GARBAGE_ALLOWANCE + 1);
- }
-} \ No newline at end of file