AMS: added caching DataInputStream object

DataInputStream is cached for the lmkd socket communication
Since the LmkdConnection ByteBuffer is allocated once,
no need to dynamically allocate DataInputStream,
just do a reset() before using

Bug: 184698933
Test: lmkd_unit_test - test check_for_oom tests lmkd message send to AMS
Test: statsd_testdrive 51 54 to inspect statsd logged atoms data
Change-Id: I9b65d82618654d59236c79be8cd8da66bc90c91c
This commit is contained in:
Vova Sharaienko
2021-05-08 00:37:25 +00:00
parent 26df817b7c
commit 42cda4953c
3 changed files with 64 additions and 51 deletions

View File

@@ -31,6 +31,8 @@ import com.android.internal.annotations.GuardedBy;
import libcore.io.IoUtils; import libcore.io.IoUtils;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@@ -74,7 +76,7 @@ public class LmkdConnection {
* @param receivedLen Size of the data received * @param receivedLen Size of the data received
* @return True if the message has been handled correctly, false otherwise. * @return True if the message has been handled correctly, false otherwise.
*/ */
boolean handleUnsolicitedMessage(ByteBuffer dataReceived, int receivedLen); boolean handleUnsolicitedMessage(DataInputStream inputData, int receivedLen);
} }
private final MessageQueue mMsgQueue; private final MessageQueue mMsgQueue;
@@ -99,6 +101,10 @@ public class LmkdConnection {
private final ByteBuffer mInputBuf = private final ByteBuffer mInputBuf =
ByteBuffer.allocate(LMKD_REPLY_MAX_SIZE); ByteBuffer.allocate(LMKD_REPLY_MAX_SIZE);
// Input stream to parse the incoming data
private final DataInputStream mInputData = new DataInputStream(
new ByteArrayInputStream(mInputBuf.array()));
// object to protect mReplyBuf and to wait/notify when reply is received // object to protect mReplyBuf and to wait/notify when reply is received
private final Object mReplyBufLock = new Object(); private final Object mReplyBufLock = new Object();
@@ -190,6 +196,9 @@ public class LmkdConnection {
private void processIncomingData() { private void processIncomingData() {
int len = read(mInputBuf); int len = read(mInputBuf);
if (len > 0) { if (len > 0) {
try {
// reset InputStream to point into mInputBuf.array() begin
mInputData.reset();
synchronized (mReplyBufLock) { synchronized (mReplyBufLock) {
if (mReplyBuf != null) { if (mReplyBuf != null) {
if (mListener.isReplyExpected(mReplyBuf, mInputBuf, len)) { if (mListener.isReplyExpected(mReplyBuf, mInputBuf, len)) {
@@ -198,19 +207,22 @@ public class LmkdConnection {
mReplyBuf.rewind(); mReplyBuf.rewind();
// wakeup the waiting thread // wakeup the waiting thread
mReplyBufLock.notifyAll(); mReplyBufLock.notifyAll();
} else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) { } else if (!mListener.handleUnsolicitedMessage(mInputData, len)) {
// received unexpected packet // received unexpected packet
// treat this as an error // treat this as an error
mReplyBuf = null; mReplyBuf = null;
mReplyBufLock.notifyAll(); mReplyBufLock.notifyAll();
Slog.e(TAG, "Received an unexpected packet from lmkd"); Slog.e(TAG, "Received an unexpected packet from lmkd");
} }
} else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) { } else if (!mListener.handleUnsolicitedMessage(mInputData, len)) {
// received asynchronous communication from lmkd // received asynchronous communication from lmkd
// but we don't recognize it. // but we don't recognize it.
Slog.w(TAG, "Received an unexpected packet from lmkd"); Slog.w(TAG, "Received an unexpected packet from lmkd");
} }
} }
} catch (IOException e) {
Slog.e(TAG, "Failed to parse lmkd data buffer. Size = " + len);
}
} }
} }

View File

@@ -23,10 +23,8 @@ import android.util.Slog;
import com.android.internal.util.FrameworkStatsLog; import com.android.internal.util.FrameworkStatsLog;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream; import java.io.DataInputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.ByteBuffer;
/** /**
* Activity manager communication with lmkd data handling and statsd atom logging * Activity manager communication with lmkd data handling and statsd atom logging
@@ -51,13 +49,8 @@ public final class LmkdStatsReporter {
* Logs the event when LMKD kills a process to reduce memory pressure. * Logs the event when LMKD kills a process to reduce memory pressure.
* Code: LMK_KILL_OCCURRED = 51 * Code: LMK_KILL_OCCURRED = 51
*/ */
public static void logKillOccurred(ByteBuffer dataReceived) { public static void logKillOccurred(DataInputStream inputData) {
DataInputStream inputData = new DataInputStream(
new ByteArrayInputStream(dataReceived.array()));
try { try {
//read first int which denotes the message type
final int msgType = inputData.readInt();
final long pgFault = inputData.readLong(); final long pgFault = inputData.readLong();
final long pgMajFault = inputData.readLong(); final long pgMajFault = inputData.readLong();
final long rssInBytes = inputData.readLong(); final long rssInBytes = inputData.readLong();

View File

@@ -139,6 +139,7 @@ import com.android.server.wm.WindowProcessController;
import dalvik.system.VMRuntime; import dalvik.system.VMRuntime;
import java.io.DataInputStream;
import java.io.File; import java.io.File;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.IOException; import java.io.IOException;
@@ -835,37 +836,44 @@ public final class ProcessList {
} }
@Override @Override
public boolean handleUnsolicitedMessage(ByteBuffer dataReceived, public boolean handleUnsolicitedMessage(DataInputStream inputData,
int receivedLen) { int receivedLen) {
if (receivedLen < 4) { if (receivedLen < 4) {
return false; return false;
} }
switch (dataReceived.getInt(0)) { try {
switch (inputData.readInt()) {
case LMK_PROCKILL: case LMK_PROCKILL:
if (receivedLen != 12) { if (receivedLen != 12) {
return false; return false;
} }
mAppExitInfoTracker.scheduleNoteLmkdProcKilled( final int pid = inputData.readInt();
dataReceived.getInt(4), dataReceived.getInt(8)); final int uid = inputData.readInt();
mAppExitInfoTracker.scheduleNoteLmkdProcKilled(pid, uid);
return true; return true;
case LMK_KILL_OCCURRED: case LMK_KILL_OCCURRED:
if (receivedLen < LmkdStatsReporter.KILL_OCCURRED_MSG_SIZE) { if (receivedLen
< LmkdStatsReporter.KILL_OCCURRED_MSG_SIZE) {
return false; return false;
} }
dataReceived.position(4); LmkdStatsReporter.logKillOccurred(inputData);
LmkdStatsReporter.logKillOccurred(dataReceived);
return true; return true;
case LMK_STATE_CHANGED: case LMK_STATE_CHANGED:
if (receivedLen != LmkdStatsReporter.STATE_CHANGED_MSG_SIZE) { if (receivedLen
!= LmkdStatsReporter.STATE_CHANGED_MSG_SIZE) {
return false; return false;
} }
LmkdStatsReporter.logStateChanged( final int state = inputData.readInt();
dataReceived.getInt(4)); LmkdStatsReporter.logStateChanged(state);
return true; return true;
default: default:
return false; return false;
} }
} catch (IOException e) {
Slog.e(TAG, "Invalid buffer data. Failed to log LMK_KILL_OCCURRED");
}
return false;
} }
} }
); );