1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.am; 18 19 import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM; 20 import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME; 21 22 import android.util.Slog; 23 24 import com.android.internal.util.FrameworkStatsLog; 25 26 import java.io.DataInputStream; 27 import java.io.IOException; 28 29 /** 30 * Activity manager communication with lmkd data handling and statsd atom logging 31 */ 32 public final class LmkdStatsReporter { 33 34 static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdStatsReporter" : TAG_AM; 35 36 public static final int KILL_OCCURRED_MSG_SIZE = 80; 37 public static final int STATE_CHANGED_MSG_SIZE = 8; 38 39 private static final int PRESSURE_AFTER_KILL = 0; 40 private static final int NOT_RESPONDING = 1; 41 private static final int LOW_SWAP_AND_THRASHING = 2; 42 private static final int LOW_MEM_AND_SWAP = 3; 43 private static final int LOW_MEM_AND_THRASHING = 4; 44 private static final int DIRECT_RECL_AND_THRASHING = 5; 45 private static final int LOW_MEM_AND_SWAP_UTIL = 6; 46 private static final int LOW_FILECACHE_AFTER_THRASHING = 7; 47 48 /** 49 * Processes the LMK_KILL_OCCURRED packet data 50 * Logs the event when LMKD kills a process to reduce memory pressure. 51 * Code: LMK_KILL_OCCURRED = 51 52 */ logKillOccurred(DataInputStream inputData)53 public static void logKillOccurred(DataInputStream inputData) { 54 try { 55 final long pgFault = inputData.readLong(); 56 final long pgMajFault = inputData.readLong(); 57 final long rssInBytes = inputData.readLong(); 58 final long cacheInBytes = inputData.readLong(); 59 final long swapInBytes = inputData.readLong(); 60 final long processStartTimeNS = inputData.readLong(); 61 final int uid = inputData.readInt(); 62 final int oomScore = inputData.readInt(); 63 final int minOomScore = inputData.readInt(); 64 final int freeMemKb = inputData.readInt(); 65 final int freeSwapKb = inputData.readInt(); 66 final int killReason = inputData.readInt(); 67 final int thrashing = inputData.readInt(); 68 final int maxThrashing = inputData.readInt(); 69 final String procName = inputData.readUTF(); 70 71 FrameworkStatsLog.write(FrameworkStatsLog.LMK_KILL_OCCURRED, uid, procName, oomScore, 72 pgFault, pgMajFault, rssInBytes, cacheInBytes, swapInBytes, processStartTimeNS, 73 minOomScore, freeMemKb, freeSwapKb, mapKillReason(killReason), thrashing, 74 maxThrashing); 75 } catch (IOException e) { 76 Slog.e(TAG, "Invalid buffer data. Failed to log LMK_KILL_OCCURRED"); 77 return; 78 } 79 } 80 81 /** 82 * Processes the LMK_STATE_CHANGED packet 83 * Logs the change in LMKD state which is used as start/stop boundaries for logging 84 * LMK_KILL_OCCURRED event. 85 * Code: LMK_STATE_CHANGED = 54 86 */ logStateChanged(int state)87 public static void logStateChanged(int state) { 88 FrameworkStatsLog.write(FrameworkStatsLog.LMK_STATE_CHANGED, state); 89 } 90 mapKillReason(int reason)91 private static int mapKillReason(int reason) { 92 switch (reason) { 93 case PRESSURE_AFTER_KILL: 94 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__PRESSURE_AFTER_KILL; 95 case NOT_RESPONDING: 96 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__NOT_RESPONDING; 97 case LOW_SWAP_AND_THRASHING: 98 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_SWAP_AND_THRASHING; 99 case LOW_MEM_AND_SWAP: 100 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_SWAP; 101 case LOW_MEM_AND_THRASHING: 102 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_THRASHING; 103 case DIRECT_RECL_AND_THRASHING: 104 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__DIRECT_RECL_AND_THRASHING; 105 case LOW_MEM_AND_SWAP_UTIL: 106 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_MEM_AND_SWAP_UTIL; 107 case LOW_FILECACHE_AFTER_THRASHING: 108 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__LOW_FILECACHE_AFTER_THRASHING; 109 default: 110 return FrameworkStatsLog.LMK_KILL_OCCURRED__REASON__UNKNOWN; 111 } 112 } 113 } 114