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

Commit 04702b8f authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "Delay Explicit GC from the SystemServer."

parents 2742da75 50d337fe
Loading
Loading
Loading
Loading
+108 −0
Original line number Diff line number Diff line
@@ -23,6 +23,14 @@ import android.util.EventLog;
import java.lang.ref.WeakReference;
import java.util.ArrayList;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.lang.Object;
/**
 * Private and debugging Binder APIs.
 * 
@@ -34,6 +42,13 @@ public class BinderInternal {
    static ArrayList<Runnable> sGcWatchers = new ArrayList<>();
    static Runnable[] sTmpWatchers = new Runnable[1];
    static long sLastGcTime;
    /* Maximum duration a GC can be delayed. */
    private static final int GC_DELAY_MAX_DURATION = 3000;
    /**
     * Maximum number of times a GC can be delayed since the
     * original request.
     */
    private static final int POSTPONED_GC_MAX = 5;

    static final class GcWatcher {
        @Override
@@ -99,7 +114,100 @@ public class BinderInternal {
        Runtime.getRuntime().gc();
    }
    
    /**
     * TimerGc Callable : Wait for a certain time, and execute the BinderGc.
     * Set the postponed count to 0.
     */
    public static class TimerGc implements Callable<Void> {
        private long waitTime;
        public TimerGc(long timeInMillis){
            this.waitTime=timeInMillis;
        }
        @Override
        public Void call() throws Exception {
            Thread.sleep(waitTime);
            forceGc("Binder");
            postponedGcCount = 0;
            return null;
        }
    }

    /**
     * lastGcDelayRequestTime records the time-stamp of the last time
     * a GC delay request was made.
     */
    static long lastGcDelayRequestTime = SystemClock.uptimeMillis();
    static TimerGc timerGcInstance = null ;
    static FutureTask<Void> futureTaskInstance = null ;
    static ExecutorService executor = Executors.newFixedThreadPool(1);
    static int postponedGcCount = 0;
    static Object delayGcMonitorObject = new Object();

    /**
     * modifyDelayedGcParams : Call from the framework based on some special Ux event.
     * like appLaunch.
     *
     * 1. If this is the first time for the trigger event, or, if there is no scheduled
     *    task, create a new FutureTaskInstance, and set the lastGcDelayRequestTime.
     *    This will be used by forceBinderGc later.
     *
     * 2. If the postponed iterations hit a maximum limit, do nothing. Let the current
     *    task execute the gc. If not,
     *
     *    a. Set the start time.
     *    b. Increment the postponed count
     *    c. Cancel the current task and start a new one for GC_DELAY_MAX_DURATION.
     */
    public static void modifyDelayedGcParams() {
        long nowTime = SystemClock.uptimeMillis();
        synchronized(delayGcMonitorObject) {
            if ((futureTaskInstance != null) && (postponedGcCount != 0)) {
                if (postponedGcCount <= POSTPONED_GC_MAX) {
                    futureTaskInstance.cancel(true);
                    if (futureTaskInstance.isCancelled()) {
                        lastGcDelayRequestTime = nowTime;
                        postponedGcCount++;
                        timerGcInstance = new TimerGc(GC_DELAY_MAX_DURATION);
                        futureTaskInstance = new FutureTask<Void>(timerGcInstance);
                        executor.execute(futureTaskInstance);
                    }
                }
            } else {
                lastGcDelayRequestTime = nowTime;
                timerGcInstance = new TimerGc(GC_DELAY_MAX_DURATION);
                futureTaskInstance = new FutureTask<Void>(timerGcInstance);
            }
        }
    }

    /**
     * Modified forceBinderGc. The brief algorithm is as follows --
     *
     * 1. If no futureTaskInstance has been initiated, directly force a BinderGc.
     * 2. Check for the duration since the last request, and see if it was within the
     *    last GC_DELAY_MAX_DURATION secs. If yes, we need to delay the GC until
     *    GC_DELAY_MAX_DURATION.
     * 3. If there is a task scheduled (postponedGcCount != 0), we merely prevent this GC,
     *    and let the GC scheduled execute.
     * 4. If no task is scheduled, we schedule one now for (GC_DELAY_MAX_DURATION - touch duration),
     *    and update postponedGcCount.
     */
    static void forceBinderGc() {
        synchronized(delayGcMonitorObject) {
            if (futureTaskInstance != null) {
                long lastGcDelayRequestDuration = (SystemClock.uptimeMillis() - lastGcDelayRequestTime);
                if (lastGcDelayRequestDuration < GC_DELAY_MAX_DURATION) {
                    if (postponedGcCount != 0)
                        return;
                    futureTaskInstance.cancel(true);
                    timerGcInstance = new TimerGc(GC_DELAY_MAX_DURATION - lastGcDelayRequestDuration);
                    futureTaskInstance = new FutureTask<Void>(timerGcInstance);
                    postponedGcCount = 1;
                    executor.execute(futureTaskInstance);
                    return;
                }
            }
        }
        forceGc("Binder");
    }
}
+3 −0
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
import com.android.server.am.ActivityStack.ActivityState;
import com.android.server.wm.WindowManagerService;
import com.android.internal.os.BinderInternal;


import java.io.FileDescriptor;
@@ -2665,6 +2666,8 @@ public final class ActivityStackSupervisor implements DisplayListener {
            mPerf.perfLockAcquire(lBoostTimeOut, lBoostPcDisblBoost, lBoostSchedBoost,
                                  lBoostCpuBoost, lBoostKsmBoost);
        }
        /* Delay Binder Explicit GC during application launch */
        BinderInternal.modifyDelayedGcParams();

        if (DEBUG_TASKS) Slog.d(TAG, "No task found");
        return null;