Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c45a5dc1 authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Support unsolicited message from lmkd"

parents b53ecd84 4fcb2a17
Loading
Loading
Loading
Loading
+17 −10
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.am;

import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;

import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;

@@ -35,9 +36,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.TimeUnit;

/**
 * Lmkd connection to communicate with lowmemorykiller daemon.
@@ -46,7 +44,7 @@ public class LmkdConnection {
    private static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdConnection" : TAG_AM;

    // lmkd reply max size in bytes
    private static final int LMKD_REPLY_MAX_SIZE = 8;
    private static final int LMKD_REPLY_MAX_SIZE = 12;

    // connection listener interface
    interface LmkdConnectionListener {
@@ -64,6 +62,15 @@ public class LmkdConnection {
         */
        public boolean isReplyExpected(ByteBuffer replyBuf, ByteBuffer dataReceived,
            int receivedLen);

        /**
         * Handle the received message if it's unsolicited.
         *
         * @param dataReceived The buffer holding received data
         * @param receivedLen Size of the data received
         * @return True if the message has been handled correctly, false otherwise.
         */
        boolean handleUnsolicitedMessage(ByteBuffer dataReceived, int receivedLen);
    }

    private final MessageQueue mMsgQueue;
@@ -187,17 +194,17 @@ public class LmkdConnection {
                        mReplyBuf.rewind();
                        // wakeup the waiting thread
                        mReplyBufLock.notifyAll();
                    } else {
                        // received asynchronous or unexpected packet
                    } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
                        // received unexpected packet
                        // treat this as an error
                        mReplyBuf = null;
                        mReplyBufLock.notifyAll();
                        Slog.e(TAG, "Received unexpected packet from lmkd");
                        Slog.e(TAG, "Received an unexpected packet from lmkd");
                    }
                } else {
                } else if (!mListener.handleUnsolicitedMessage(mInputBuf, len)) {
                    // received asynchronous communication from lmkd
                    // we don't support this yet
                    Slog.w(TAG, "Received an asynchronous packet from lmkd");
                    // but we don't recognize it.
                    Slog.w(TAG, "Received an unexpected packet from lmkd");
                }
            }
        }
+72 −9
Original line number Diff line number Diff line
@@ -278,14 +278,16 @@ public final class ProcessList {
    // LMK_PROCREMOVE <pid>
    // LMK_PROCPURGE
    // LMK_GETKILLCNT
    // LMK_PROCKILL
    static final byte LMK_TARGET = 0;
    static final byte LMK_PROCPRIO = 1;
    static final byte LMK_PROCREMOVE = 2;
    static final byte LMK_PROCPURGE = 3;
    static final byte LMK_GETKILLCNT = 4;
    static final byte LMK_PROCKILL = 5; // Note: this is an unsolicated command

    // lmkd reconnect delay in msecs
    private final static long LMDK_RECONNECT_DELAY_MS = 1000;
    private static final long LMKD_RECONNECT_DELAY_MS = 1000;

    /**
     * How long between a process kill and we actually receive its death recipient
@@ -390,6 +392,12 @@ public final class ProcessList {

    ActiveUids mActiveUids;

    /**
     * The listener who is intereted with the lmkd kills.
     */
    @GuardedBy("mService")
    private LmkdKillListener mLmkdKillListener = null;

    /**
     * The currently running isolated processes.
     */
@@ -408,6 +416,13 @@ public final class ProcessList {

    private PlatformCompat mPlatformCompat = null;

    interface LmkdKillListener {
        /**
         * Called when there is a process kill by lmkd.
         */
        void onLmkdKillOccurred(int pid, int uid);
    }

    final class IsolatedUidRange {
        @VisibleForTesting
        public final int mFirstUid;
@@ -560,7 +575,8 @@ public final class ProcessList {

    final class KillHandler extends Handler {
        static final int KILL_PROCESS_GROUP_MSG = 4000;
        static final int LMDK_RECONNECT_MSG = 4001;
        static final int LMKD_RECONNECT_MSG = 4001;
        static final int LMKD_PROC_KILLED_MSG = 4002;

        public KillHandler(Looper looper) {
            super(looper, null, true);
@@ -574,15 +590,18 @@ public final class ProcessList {
                    Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
                case LMDK_RECONNECT_MSG:
                case LMKD_RECONNECT_MSG:
                    if (!sLmkdConnection.connect()) {
                        Slog.i(TAG, "Failed to connect to lmkd, retry after " +
                                LMDK_RECONNECT_DELAY_MS + " ms");
                        // retry after LMDK_RECONNECT_DELAY_MS
                                LMKD_RECONNECT_DELAY_MS + " ms");
                        // retry after LMKD_RECONNECT_DELAY_MS
                        sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
                                KillHandler.LMDK_RECONNECT_MSG), LMDK_RECONNECT_DELAY_MS);
                                KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS);
                    }
                    break;
                case LMKD_PROC_KILLED_MSG:
                    handleLmkdProcKilled(msg.arg1 /* pid */, msg.arg2 /* uid */);
                    break;

                default:
                    super.handleMessage(msg);
@@ -623,7 +642,7 @@ public final class ProcessList {
                            Slog.w(TAG, "Lost connection to lmkd");
                            // start reconnection after delay to let lmkd restart
                            sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
                                    KillHandler.LMDK_RECONNECT_MSG), LMDK_RECONNECT_DELAY_MS);
                                    KillHandler.LMKD_RECONNECT_MSG), LMKD_RECONNECT_DELAY_MS);
                        }

                        @Override
@@ -634,6 +653,26 @@ public final class ProcessList {
                            return (receivedLen == replyBuf.array().length &&
                                    dataReceived.getInt(0) == replyBuf.getInt(0));
                        }

                        @Override
                        public boolean handleUnsolicitedMessage(ByteBuffer dataReceived,
                                int receivedLen) {
                            if (receivedLen < 4) {
                                return false;
                            }
                            switch (dataReceived.getInt(0)) {
                                case LMK_PROCKILL:
                                    if (receivedLen != 12) {
                                        return false;
                                    }
                                    sKillHandler.obtainMessage(KillHandler.LMKD_PROC_KILLED_MSG,
                                            dataReceived.getInt(4), dataReceived.getInt(8))
                                            .sendToTarget();
                                    return true;
                                default:
                                    return false;
                            }
                        }
                    }
            );
        }
@@ -1310,10 +1349,10 @@ public final class ProcessList {
        if (!sLmkdConnection.isConnected()) {
            // try to connect immediately and then keep retrying
            sKillHandler.sendMessage(
                sKillHandler.obtainMessage(KillHandler.LMDK_RECONNECT_MSG));
                    sKillHandler.obtainMessage(KillHandler.LMKD_RECONNECT_MSG));

            // wait for connection retrying 3 times (up to 3 seconds)
            if (!sLmkdConnection.waitForConnection(3 * LMDK_RECONNECT_DELAY_MS)) {
            if (!sLmkdConnection.waitForConnection(3 * LMKD_RECONNECT_DELAY_MS)) {
                return false;
            }
        }
@@ -3405,4 +3444,28 @@ public final class ProcessList {
            }
        }
    }

    void setLmkdKillListener(final LmkdKillListener listener) {
        synchronized (mService) {
            mLmkdKillListener = listener;
        }
    }

    private void handleLmkdProcKilled(final int pid, final int uid) {
        // Log only now
        if (DEBUG_PROCESSES) {
            Slog.i(TAG, "lmkd kill: pid=" + pid + " uid=" + uid);
        }

        if (mService == null) {
            return;
        }
        // Notify any interesed party regarding the lmkd kills
        synchronized (mService) {
            final LmkdKillListener listener = mLmkdKillListener;
            if (listener != null) {
                mService.mHandler.post(()-> listener.onLmkdKillOccurred(pid, uid));
            }
        }
    }
}