android通过广播打印ram使用信息

在内存非常吃紧的情况下,android设备会开始kill部分非系统进程甚至系统进程来保证基本的系统运行。在这种情况下如何获取设备过去某段时间的ram使用情况至关重要。

通过开发者模式中的"内存"可以完美得知设备内存使用信息。

我们可以通过此途径,设计一套通过广播打印内存信息的方式以应对各种调试情况,此文仅将内存信息通过log的形式后台打印获取。

1.发送的广播需要在BroadcastQueue.java特别处理,避免被系统拦截。

2.为了避免各种权限问题,将此套方案耦合在Settings模组。

3.RamInfo参考开发者模式中的方式获取过去某段时间的内存使用情况。

java 复制代码
Index: frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java
===================================================================
--- frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java	(版本 10810)
+++ frameworks/base/services/core/java/com/android/server/am/BroadcastQueue.java	(版本 10827)
@@ -121,6 +121,7 @@
+        sBackgroundActionWhiteListArraySet.add("com.android.settings.action.RAM_INFO");
     }
 
Index: packages/apps/Settings/src/com/android/settings/applications/RamInfo.java
===================================================================
--- packages/apps/Settings/src/com/android/settings/applications/RamInfo.java	(不存在的)
+++ packages/apps/Settings/src/com/android/settings/applications/RamInfo.java	(版本 10827)
@@ -0,0 +1,120 @@
+package com.android.settings.applications;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.text.format.Formatter;
+import android.text.format.Formatter.BytesResult;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.applications.ProcStatsData.MemInfo;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class RamInfo extends BroadcastReceiver {
+
+    private static String TAG ="RamInfo";
+
+    private PackageManager mPm;
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.d(TAG, "onReceive:" + intent.getAction());
+
+        int index = intent.getIntExtra("index", 3); // 0 - 3h, 1 - 6h, 2 - 12h, 3 - 24h
+
+        mPm = context.getPackageManager();
+
+        ProcStatsData statsManager = new ProcStatsData(context, false);
+        statsManager.setDuration(ProcessStatsBase.sDurations[index]);
+
+        MemInfo memInfo = statsManager.getMemInfo();
+        double usedRam = memInfo.realUsedRam;
+        double totalRam = memInfo.realTotalRam;
+        double freeRam = memInfo.realFreeRam;
+        BytesResult usedResult = Formatter.formatBytes(context.getResources(), (long) usedRam,
+                Formatter.FLAG_SHORTER);
+        String totalString = Formatter.formatShortFileSize(context, (long) totalRam);
+        String freeString = Formatter.formatShortFileSize(context, (long) freeRam);
+        CharSequence memString;
+        CharSequence[] memStatesStr = context.getResources().getTextArray(R.array.ram_states);
+        int memState = statsManager.getMemState();
+        if (memState >= 0 && memState < memStatesStr.length - 1) {
+            memString = memStatesStr[memState];
+        } else {
+            memString = memStatesStr[memStatesStr.length - 1];
+        }
+        String durationString = context.getResources().getString(ProcessStatsBase.sDurationLabels[index]);
+        int numApps = statsManager.getEntries().size();
+
+        Log.d(TAG, "********** RAM INFO (" + durationString + ") **********");
+        // Average
+        Log.d(TAG, context.getResources().getString(R.string.memory_avg_use) + ": " + usedResult.value + usedResult.units);
+        // Performance
+        Log.d(TAG, context.getResources().getString(R.string.memory_performance) + ": " + memString);
+        // Total memory
+        Log.d(TAG, context.getResources().getString(R.string.total_memory) + ": " + totalString);
+        // Average used
+        Log.d(TAG, context.getResources().getString(R.string.average_used) + ": " + (Utils.formatPercentage((long) usedRam, (long) totalRam)));
+        // Free
+        Log.d(TAG, context.getResources().getString(R.string.free_memory) + ": " + freeString);
+        // Memory used by apps
+        Log.d(TAG, context.getResources().getString(R.string.memory_usage_apps)+ ": " + context.getResources().getQuantityString(
+                R.plurals.memory_usage_apps_summary, numApps, numApps, durationString));
+
+        boolean mShowMax = false;
+
+        List<ProcStatsPackageEntry> pkgEntries = statsManager.getEntries();
+
+        // Update everything and get the absolute maximum of memory usage for scaling.
+        for (int i = 0, N = pkgEntries.size(); i < N; i++) {
+            ProcStatsPackageEntry pkg = pkgEntries.get(i);
+            pkg.updateMetrics();
+        }
+
+        Collections.sort(pkgEntries, mShowMax ? sMaxPackageEntryCompare : sPackageEntryCompare);
+
+        for (int i = 0; i < pkgEntries.size(); i++) {
+            ProcStatsPackageEntry pkg = pkgEntries.get(i);
+            pkg.retrieveUiData(context, mPm);
+            boolean statsForeground = pkg.mRunWeight > pkg.mBgWeight;
+            double avgAmount = (statsForeground ? pkg.mRunWeight : pkg.mBgWeight) * memInfo.weightToRam;
+            double maxAmount = (statsForeground ? pkg.mMaxRunMem : pkg.mMaxBgMem) * memInfo.totalScale * 1024;
+            Log.d(TAG, pkg.mUiLabel + "(" + pkg.mPackage + ")" + 
+                    " {" + context.getResources().getString(R.string.memory_avg_use) + ":" + Formatter.formatShortFileSize(context, (long) avgAmount) + " " +
+                    context.getResources().getString(R.string.memory_max_use) + ":" + Formatter.formatShortFileSize(context, (long) maxAmount) + "}");
+        }
+        Log.d(TAG, "********** RAM INFO END **********");
+    }
+
+    final static Comparator<ProcStatsPackageEntry> sPackageEntryCompare
+            = new Comparator<ProcStatsPackageEntry>() {
+        @Override
+        public int compare(ProcStatsPackageEntry lhs, ProcStatsPackageEntry rhs) {
+            double rhsWeight = Math.max(rhs.mRunWeight, rhs.mBgWeight);
+            double lhsWeight = Math.max(lhs.mRunWeight, lhs.mBgWeight);
+            if (lhsWeight == rhsWeight) {
+                return 0;
+            }
+            return lhsWeight < rhsWeight ? 1 : -1;
+        }
+    };
+
+    final static Comparator<ProcStatsPackageEntry> sMaxPackageEntryCompare
+            = new Comparator<ProcStatsPackageEntry>() {
+        @Override
+        public int compare(ProcStatsPackageEntry lhs, ProcStatsPackageEntry rhs) {
+            double rhsMax = Math.max(rhs.mMaxBgMem, rhs.mMaxRunMem);
+            double lhsMax = Math.max(lhs.mMaxBgMem, lhs.mMaxRunMem);
+            if (lhsMax == rhsMax) {
+                return 0;
+            }
+            return lhsMax < rhsMax ? 1 : -1;
+        }
+    };
+}
\ No newline at end of file
Index: packages/apps/Settings/AndroidManifest.xml
===================================================================
--- packages/apps/Settings/AndroidManifest.xml	(版本 10810)
+++ packages/apps/Settings/AndroidManifest.xml	(版本 10827)
@@ -3603,5 +3603,11 @@
             </intent-filter>
         </receiver> 
+
+        <receiver android:name=".applications.RamInfo">
+            <intent-filter>    
+                <action android:name="com.android.settings.action.RAM_INFO" />
+            </intent-filter>
+        </receiver> 
     </application>
 </manifest>
相关推荐
JMchen1239 小时前
现代Android图像处理管道:从CameraX到OpenGL的60fps实时滤镜架构
android·图像处理·架构·kotlin·android studio·opengl·camerax
快点好好学习吧10 小时前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
是誰萆微了承諾10 小时前
php 对接deepseek
android·开发语言·php
Dxy123931021611 小时前
MySQL如何加唯一索引
android·数据库·mysql
冠希陈、13 小时前
PHP 判断是否是移动端,更新鸿蒙系统
android·开发语言·php
晚霞的不甘15 小时前
Flutter for OpenHarmony从零到一:构建《冰火人》双人合作闯关游戏
android·flutter·游戏·前端框架·全文检索·交互
2601_9498333915 小时前
flutter_for_openharmony口腔护理app实战+饮食记录实现
android·javascript·flutter
独自破碎E15 小时前
【滑动窗口+字符计数数组】LCR_014_字符串的排列
android·java·开发语言
stevenzqzq16 小时前
compose 中 align和Arrangement的区别
android·compose
VincentWei9516 小时前
Compose:MutableState 和 mutableStateOf
android