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

Commit 16045c24 authored by Stefan Kuhne's avatar Stefan Kuhne
Browse files

Adding am send-trim-memory command

This patch adds a send-trim-memory command to the ActivityManager to allow
for better debugging&testing.

The command is
adb shell am send-trim-memory [--user <USER_ID>] <PROCESS> <LEVEL>
whereas LEVEL can be one of the following:
[HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|
 RUNNING_CRITICAL|COMPLETE]

Bug: 21633189
Change-Id: I7a41ce02c3c9043ffd3e5aaa791f7b7306a9de49
parent e7f68c18
Loading
Loading
Loading
Loading
+62 −5
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.app.UiAutomationConnection;
import android.app.usage.ConfigurationStats;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageStatsManager;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
import android.content.Context;
import android.content.IIntentReceiver;
@@ -144,6 +145,8 @@ public class Am extends BaseCommand {
                "       am get-config\n" +
                "       am set-inactive [--user <USER_ID>] <PACKAGE> true|false\n" +
                "       am get-inactive [--user <USER_ID>] <PACKAGE>\n" +
                "       am send-trim-memory [--user <USER_ID>] <PROCESS>\n" +
                "               [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]\n" +
                "\n" +
                "am start: start an Activity.  Options are:\n" +
                "    -D: enable debugging\n" +
@@ -271,9 +274,9 @@ public class Am extends BaseCommand {
                "\n" +
                "am stack info: display the information about activity stack <STACK_ID>.\n" +
                "\n" +
                "am task lock: bring <TASK_ID> to the front and don't allow other tasks to run\n" +
                "am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.\n" +
                "\n" +
                "am task lock stop: end the current task lock\n" +
                "am task lock stop: end the current task lock.\n" +
                "\n" +
                "am task resizeable: change if <TASK_ID> is resizeable (true) or not (false).\n" +
                "\n" +
@@ -282,12 +285,13 @@ public class Am extends BaseCommand {
                "   has the specified bounds.\n" +
                "\n" +
                "am get-config: retrieve the configuration and any recent configurations\n" +
                "  of the device\n" +
                "  of the device.\n" +
                "\n" +
                "am set-inactive: sets the inactive state of an app\n" +
                "am set-inactive: sets the inactive state of an app.\n" +
                "\n" +
                "am get-inactive: returns the inactive state of an app\n" +
                "am get-inactive: returns the inactive state of an app.\n" +
                "\n" +
                " am send-trim-memory: Send a memory trim event to a <PROCESS>.\n" +
                "\n" +
                "<INTENT> specifications include these flags and arguments:\n" +
                "    [-a <ACTION>] [-d <DATA_URI>] [-t <MIME_TYPE>]\n" +
@@ -399,6 +403,8 @@ public class Am extends BaseCommand {
            runSetInactive();
        } else if (op.equals("get-inactive")) {
            runGetInactive();
        } else if (op.equals("send-trim-memory")) {
            runSendTrimMemory();
        } else {
            showError("Error: unknown command '" + op + "'");
        }
@@ -2070,6 +2076,57 @@ public class Am extends BaseCommand {
        System.out.println("Idle=" + isIdle);
    }

    private void runSendTrimMemory() throws Exception {
        int userId = UserHandle.USER_CURRENT;
        String opt;
        while ((opt = nextOption()) != null) {
            if (opt.equals("--user")) {
                userId = parseUserArg(nextArgRequired());
                if (userId == UserHandle.USER_ALL) {
                    System.err.println("Error: Can't use user 'all'");
                    return;
                }
            } else {
                System.err.println("Error: Unknown option: " + opt);
                return;
            }
        }

        String proc = nextArgRequired();
        String levelArg = nextArgRequired();
        int level;
        switch (levelArg) {
            case "HIDDEN":
                level = ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN;
                break;
            case "RUNNING_MODERATE":
                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE;
                break;
            case "BACKGROUND":
                level = ComponentCallbacks2.TRIM_MEMORY_BACKGROUND;
                break;
            case "RUNNING_LOW":
                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW;
                break;
            case "MODERATE":
                level = ComponentCallbacks2.TRIM_MEMORY_MODERATE;
                break;
            case "RUNNING_CRITICAL":
                level = ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL;
                break;
            case "COMPLETE":
                level = ComponentCallbacks2.TRIM_MEMORY_COMPLETE;
                break;
            default:
                System.err.println("Error: Unknown level option: " + levelArg);
                return;
        }
        if (!mAm.setProcessMemoryTrimLevel(proc, userId, level)) {
            System.err.println("Error: Failure to set the level - probably Unknown Process: " +
                               proc);
        }
    }

    /**
     * Open the given file for sending into the system process. This verifies
     * with SELinux that the system will have access to the file.
+83 −66
Original line number Diff line number Diff line
@@ -2296,6 +2296,23 @@ public class ActivityManager {
        }
    }

    /**
     * Sets the memory trim mode for a process and schedules a memory trim operation.
     *
     * <p><b>Note: this method is only intended for testing framework.</b></p>
     *
     * @return Returns true if successful.
     * @hide
     */
    public boolean setProcessMemoryTrimLevel(String process, int userId, int level) {
        try {
            return ActivityManagerNative.getDefault().setProcessMemoryTrimLevel(process, userId,
                    level);
        } catch (RemoteException e) {
            return false;
        }
    }

    /**
     * Returns a list of application processes that are running on the device.
     *
@@ -2697,7 +2714,7 @@ public class ActivityManager {
    }

    /**
     * @param userid the user's id. Zero indicates the default user 
     * @param userid the user's id. Zero indicates the default user.
     * @hide
     */
    public boolean switchUser(int userid) {
+49 −21
Original line number Diff line number Diff line
@@ -2548,6 +2548,17 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
            reply.writeInt(res);
            return true;
        }

        case SET_PROCESS_MEMORY_TRIM_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            String process = data.readString();
            int userId = data.readInt();
            int level = data.readInt();
            boolean res = setProcessMemoryTrimLevel(process, userId, level);
            reply.writeNoException();
            reply.writeInt(res ? 1 : 0);
            return true;
        }
        }

        return super.onTransact(code, data, reply, flags);
@@ -5880,5 +5891,22 @@ class ActivityManagerProxy implements IActivityManager
        return res;
    }

    @Override
    public boolean setProcessMemoryTrimLevel(String process, int userId, int level)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeString(process);
        data.writeInt(userId);
        data.writeInt(level);
        mRemote.transact(SET_PROCESS_MEMORY_TRIM_TRANSACTION, data, reply, 0);
        reply.readException();
        int res = reply.readInt();
        data.recycle();
        reply.recycle();
        return res != 0;
    }

    private IBinder mRemote;
}
+10 −6
Original line number Diff line number Diff line
@@ -505,6 +505,9 @@ public interface IActivityManager extends IInterface {

    public int getPackageProcessState(String packageName) throws RemoteException;

    public boolean setProcessMemoryTrimLevel(String process, int uid, int level)
            throws RemoteException;

    /*
     * Private non-Binder interfaces
     */
@@ -790,6 +793,7 @@ public interface IActivityManager extends IInterface {
    // Available
    int GET_ACTIVITY_DISPLAY_ID_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+184;
    int DELETE_ACTIVITY_CONTAINER_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+185;
    int SET_PROCESS_MEMORY_TRIM_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+186;


    // Start of L transactions
+20 −0
Original line number Diff line number Diff line
@@ -3613,6 +3613,26 @@ public final class ActivityManagerService extends ActivityManagerNative
        return procState;
    }
    @Override
    public boolean setProcessMemoryTrimLevel(String process, int userId, int level) {
        ProcessRecord app = getProcessRecordLocked(process, userId, true);
        if (app == null) {
            return false;
        }
        if (app.trimMemoryLevel < level && app.thread != null &&
                (level < ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN ||
                        app.trimMemoryLevel >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN)) {
            try {
                app.thread.scheduleTrimMemory(level);
                app.trimMemoryLevel = level;
                return true;
            } catch (RemoteException e) {
                // Fallthrough to failure case.
            }
        }
        return false;
    }
    private void dispatchProcessesChanged() {
        int N;
        synchronized (this) {