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

Commit 125134ba authored by Michael Wachenschwanz's avatar Michael Wachenschwanz
Browse files

Batch Service related PSC updates

The ProcessStateController BatchSession will prevent any OomAdjuster
update from being triggered until the BatchSession is over. Throughout
the Service management code are nested methods that may trigger
OomAdjuster updates and result in many unnecessary back to back
updates. Wrapping high level flows with a BatchSession will collapse
all attempted update triggers into one large update that handles all
processes being updated.

Flag: com.android.server.am.psc_batch_service_updates
Bug: 437171290
Test: atest android.app.cts.service.ServiceTest
Change-Id: I4e2357b808e86806f555b34cc237324e84a718bd
parent 02af4d4b
Loading
Loading
Loading
Loading
+791 −642

File changed.

Preview size limit exceeded, changes collapsed.

+14 −7
Original line number Diff line number Diff line
@@ -3503,9 +3503,12 @@ public class ActivityManagerService extends IActivityManager.Stub
                app.forEachConnectionHost((host) -> enqueueOomAdjTargetLocked(host));
            }
            EventLogTags.writeAmProcDied(app.userId, pid, app.processName, setAdj, setProcState);
            if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP,
                "Dying app: " + app + ", pid: " + pid + ", thread: " + thread.asBinder());
            EventLogTags.writeAmProcDied(app.userId, pid, app.processName, setAdj,
                    setProcState);
            if (DEBUG_CLEANUP) {
                Slog.v(TAG_CLEANUP, "Dying app: " + app + ", pid: " + pid + ", thread: "
                        + thread.asBinder());
            }
            handleAppDiedLocked(app, pid, false, true, fromBinderDied);
            if (doOomAdj) {
@@ -17478,13 +17481,17 @@ public class ActivityManagerService extends IActivityManager.Stub
            final ActivityServiceConnectionsHolder holder =
                    (ActivityServiceConnectionsHolder) connectionHolder;
            synchronized (ActivityManagerService.this) {
                try (var unused = mProcessStateController.startServiceBatchSession(
                        OOM_ADJ_REASON_UNBIND_SERVICE)) {
                    synchronized (mProcLock) {
                    holder.forEachConnection(cr -> mServices.removeConnectionLocked(
                            (ConnectionRecord) cr, null /* skipApp */, holder /* skipAct */,
                        holder.forEachConnection(
                                cr -> mServices.removeConnectionLocked((ConnectionRecord) cr,
                                        null /* skipApp */, holder /* skipAct */,
                                        false /* enqueueOomAdj */));
                    }
                }
            }
        }
        public void cleanUpServices(int userId, ComponentName component, Intent baseIntent) {
            synchronized(ActivityManagerService.this) {
+28 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.server.am.psc.AsyncBatchSession;
import com.android.server.am.psc.ProcessRecordInternal;
import com.android.server.am.psc.ServiceRecordInternal;
import com.android.server.am.psc.SyncBatchSession;
import com.android.server.am.psc.annotation.RequiresEnclosingBatchSession;
import com.android.server.wm.WindowProcessController;

import java.lang.ref.WeakReference;
@@ -101,6 +102,18 @@ public class ProcessStateController {

    }

    /**
     * Start a batch session for specifically service state changes. ProcessStateController updates
     * will not be triggered until until the returned SyncBatchSession is closed.
     */
    public SyncBatchSession startServiceBatchSession(@OomAdjReason int reason) {
        if (!Flags.pscBatchServiceUpdates()) return null;

        final SyncBatchSession batchSession = getBatchSession();
        batchSession.start(reason);
        return batchSession;
    }

    /**
     * Start a batch session. ProcessStateController updates will not be triggered until the
     * returned SyncBatchSession is closed.
@@ -641,6 +654,7 @@ public class ProcessStateController {
     * Note that a process has started hosting a service.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public boolean startService(@NonNull ProcessServiceRecord psr, ServiceRecord sr) {
        return psr.startService(sr);
    }
@@ -649,6 +663,7 @@ public class ProcessStateController {
     * Note that a process has stopped hosting a service.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public boolean stopService(@NonNull ProcessServiceRecord psr, ServiceRecord sr) {
        return psr.stopService(sr);
    }
@@ -657,6 +672,7 @@ public class ProcessStateController {
     * Remove all services that the process is hosting.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void stopAllServices(@NonNull ProcessServiceRecord psr) {
        psr.stopAllServices();
    }
@@ -665,6 +681,7 @@ public class ProcessStateController {
     * Note that a process's service has started executing.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void startExecutingService(@NonNull ProcessServiceRecord psr, ServiceRecord sr) {
        psr.startExecutingService(sr);
    }
@@ -673,6 +690,7 @@ public class ProcessStateController {
     * Note that a process's service has stopped executing.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void stopExecutingService(@NonNull ProcessServiceRecord psr, ServiceRecord sr) {
        psr.stopExecutingService(sr);
    }
@@ -681,6 +699,7 @@ public class ProcessStateController {
     * Note all executing services a process has has stopped.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void stopAllExecutingServices(@NonNull ProcessServiceRecord psr) {
        psr.stopAllExecutingServices();
    }
@@ -689,6 +708,7 @@ public class ProcessStateController {
     * Note that process has bound to a service.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void addConnection(@NonNull ProcessServiceRecord psr, ConnectionRecord cr) {
        psr.addConnection(cr);
    }
@@ -697,6 +717,7 @@ public class ProcessStateController {
     * Note that process has unbound from a service.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void removeConnection(@NonNull ProcessServiceRecord psr, ConnectionRecord cr) {
        psr.removeConnection(cr);
    }
@@ -705,6 +726,7 @@ public class ProcessStateController {
     * Remove all bindings a process has to services.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void removeAllConnections(@NonNull ProcessServiceRecord psr) {
        psr.removeAllConnections();
        psr.removeAllSdkSandboxConnections();
@@ -714,6 +736,7 @@ public class ProcessStateController {
     * Note whether an executing service should be considered in the foreground or not.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void setExecServicesFg(@NonNull ProcessServiceRecord psr, boolean execServicesFg) {
        psr.setExecServicesFg(execServicesFg);
    }
@@ -722,6 +745,7 @@ public class ProcessStateController {
     * Note whether a service is in the foreground or not and what type of FGS, if so.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void setHasForegroundServices(@NonNull ProcessServiceRecord psr,
            boolean hasForegroundServices,
            int fgServiceTypes, boolean hasTypeNoneFgs) {
@@ -732,6 +756,7 @@ public class ProcessStateController {
     * Note whether a service has a client activity or not.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void setHasClientActivities(@NonNull ProcessServiceRecord psr,
            boolean hasClientActivities) {
        psr.setHasClientActivities(hasClientActivities);
@@ -741,6 +766,7 @@ public class ProcessStateController {
     * Note whether a service should be treated like an activity or not.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void setTreatLikeActivity(@NonNull ProcessServiceRecord psr, boolean treatLikeActivity) {
        psr.setTreatLikeActivity(treatLikeActivity);
    }
@@ -757,6 +783,7 @@ public class ProcessStateController {
     * {@link android.content.Context.BIND_ABOVE_CLIENT} or not.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void setHasAboveClient(@NonNull ProcessServiceRecord psr, boolean hasAboveClient) {
        psr.setHasAboveClient(hasAboveClient);
    }
@@ -766,6 +793,7 @@ public class ProcessStateController {
     * {@link android.content.Context.BIND_ABOVE_CLIENT} or not.
     */
    @GuardedBy("mLock")
    @RequiresEnclosingBatchSession
    public void updateHasAboveClientLocked(@NonNull ProcessServiceRecord psr) {
        psr.updateHasAboveClientLocked();
    }
+10 −0
Original line number Diff line number Diff line
@@ -262,3 +262,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "psc_batch_service_updates"
    namespace: "backstage_power"
    description: "Batch Service related ProcessStateController updates and auto trigger the update on state changes."
    bug: "399680824"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
 No newline at end of file
+3 −0
Original line number Diff line number Diff line
@@ -30,6 +30,9 @@ import java.util.Arrays;
 * A simple tool for tracking the concept of a process state change "session". Session starts can
 * be nested and a session is considered active until every start has an accompanying close.
 *
 * A BatchSession must be active when a method annotated with
 * {@link com.android.server.am.psc.annotation.RequiresEnclosingBatchSession} is called.
 *
 * BatchSession is not thread-safe and should only be used within the same thread or lock.
 */
@RavenwoodKeepWholeClass
Loading