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

Commit a631d56c authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Add new API to performing grouping and ordering of bindings.

This will allow apps to better manage many isolated processes,
telling the system how they are grouped together (so should be
managed as one related entity within the LRU cache) and fine-tune
the ordering within that group.

The API is not yet tested...  though in theory it is implemented.
But the implementation done for that also fixes a *lot* of problems
with activity LRU management that, even without groups, should
make the ordering of processes in the LRU list much more consistently
match how recently the user has interacted with it.

Also clean up some of the new dumpsys output in the activity manager:
move the new sections to before the process output (so it is still
easy to see the process state at the end of the output), and add and
document the command line options for controlling them.  And add a
new "lru" section that gives a clear view of what is going on with
the raw LRU list.

An upcoming change will add tests for the new grouping functionality,
and probably some fixes resulting from that.

Test: atest CtsAppTestCases:ServiceTest
Bug: 111434506
Change-Id: I1f6b6b9de66ccde1573e1a0e9615e8c5f8e6c0d7
parent f66699ae
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -9598,6 +9598,7 @@ package android.content {
    method public abstract void unbindService(android.content.ServiceConnection);
    method public void unregisterComponentCallbacks(android.content.ComponentCallbacks);
    method public abstract void unregisterReceiver(android.content.BroadcastReceiver);
    method public abstract void updateServiceGroup(android.content.ServiceConnection, int, int);
    field public static final java.lang.String ACCESSIBILITY_SERVICE = "accessibility";
    field public static final java.lang.String ACCOUNT_SERVICE = "account";
    field public static final java.lang.String ACTIVITY_SERVICE = "activity";
@@ -9796,6 +9797,7 @@ package android.content {
    method public boolean stopService(android.content.Intent);
    method public void unbindService(android.content.ServiceConnection);
    method public void unregisterReceiver(android.content.BroadcastReceiver);
    method public void updateServiceGroup(android.content.ServiceConnection, int, int);
  }
  public deprecated class CursorLoader extends android.content.AsyncTaskLoader {
+18 −0
Original line number Diff line number Diff line
@@ -1723,6 +1723,24 @@ class ContextImpl extends Context {
        }
    }

    @Override
    public void updateServiceGroup(@NonNull ServiceConnection conn, int group, int importance) {
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
            IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
                    getOuterContext(), conn);
            try {
                ActivityManager.getService().updateServiceGroup(sd, group, importance);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } else {
            throw new RuntimeException("Not supported in system context");
        }
    }

    @Override
    public void unbindService(ServiceConnection conn) {
        if (conn == null) {
+1 −0
Original line number Diff line number Diff line
@@ -140,6 +140,7 @@ interface IActivityManager {
    int bindIsolatedService(in IApplicationThread caller, in IBinder token, in Intent service,
            in String resolvedType, in IServiceConnection connection, int flags,
            in String instanceName, in String callingPackage, int userId);
    void updateServiceGroup(in IServiceConnection connection, int group, int importance);
    boolean unbindService(in IServiceConnection connection);
    void publishService(in IBinder token, in Intent intent, in IBinder service);
    void setDebugApp(in String packageName, boolean waitForDebugger, boolean persistent);
+34 −0
Original line number Diff line number Diff line
@@ -425,6 +425,15 @@ public abstract class Context {
     */
    public static final int BIND_EXTERNAL_SERVICE = 0x80000000;

    /**
     * These bind flags reduce the strength of the binding such that we shouldn't
     * consider it as pulling the process up to the level of the one that is bound to it.
     * @hide
     */
    public static final int BIND_REDUCTION_FLAGS =
            Context.BIND_ALLOW_OOM_MANAGEMENT | Context.BIND_WAIVE_PRIORITY
                    | Context.BIND_ADJUST_BELOW_PERCEPTIBLE | Context.BIND_NOT_VISIBLE;

    /** @hide */
    @IntDef(flag = true, prefix = { "RECEIVER_VISIBLE_" }, value = {
            RECEIVER_VISIBLE_TO_INSTANT_APPS
@@ -2981,6 +2990,31 @@ public abstract class Context {
        throw new RuntimeException("Not implemented. Must override in a subclass.");
    }

    /**
     * For a service previously bound with {@link #bindService} or a related method, change
     * how the system manages that service's process in relation to other processes.  This
     * doesn't modify the original bind flags that were passed in when binding, but adjusts
     * how the process will be managed in some cases based on those flags.  Currently only
     * works on isolated processes (will be ignored for non-isolated processes).
     *
     * @param conn The connection interface previously supplied to bindService().  This
     *             parameter must not be null.
     * @param group A group to put this connection's process in.  Upon calling here, this
     *              will override any previous group that was set for that process.  The group
     *              tells the system about processes that are logically grouped together, so
     *              should be managed as one unit of importance (such as when being considered
     *              a recently used app).  All processes in the same app with the same group
     *              are considered to be related.  Supplying 0 reverts to the default behavior
     *              of not grouping.
     * @param importance Additional importance of the processes within a group.  Upon calling
     *                   here, this will override any previous group that was set for that
     *                   process.  This fine-tunes process killing of all processes within
     *                   a related groups -- higher importance values will be killed before
     *                   lower ones.
     */
    public abstract void updateServiceGroup(@NonNull ServiceConnection conn, int group,
            int importance);

    /**
     * Disconnect from an application service.  You will no longer receive
     * calls as the service is restarted, and the service is now allowed to
+5 −0
Original line number Diff line number Diff line
@@ -725,6 +725,11 @@ public class ContextWrapper extends Context {
        return mBase.bindServiceAsUser(service, conn, flags, handler, user);
    }

    @Override
    public void updateServiceGroup(ServiceConnection conn, int group, int importance) {
        mBase.updateServiceGroup(conn, group, importance);
    }

    @Override
    public void unbindService(ServiceConnection conn) {
        mBase.unbindService(conn);
Loading