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

Commit 88454935 authored by Dmitri Plotnikov's avatar Dmitri Plotnikov
Browse files

Give JobScheduler its own background thread

Test: atest android.jobscheduler.cts
Bug: 142281756

Change-Id: I7de50f7e20d8df773b85992f44704ee2c99eb90a
parent 2d1ef477
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -79,7 +79,6 @@ import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IBatteryStats;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
@@ -1893,7 +1892,7 @@ public class DeviceIdleController extends SystemService
        }

        MyHandler getHandler(DeviceIdleController controller) {
            return controller.new MyHandler(BackgroundThread.getHandler().getLooper());
            return controller.new MyHandler(JobSchedulerBackgroundThread.getHandler().getLooper());
        }

        Sensor getMotionSensor() {
@@ -1960,7 +1959,8 @@ public class DeviceIdleController extends SystemService
        mInjector = injector;
        mConfigFile = new AtomicFile(new File(getSystemDir(), "deviceidle.xml"));
        mHandler = mInjector.getHandler(this);
        mAppStateTracker = mInjector.getAppStateTracker(context, FgThread.get().getLooper());
        mAppStateTracker = mInjector.getAppStateTracker(context,
                JobSchedulerBackgroundThread.get().getLooper());
        LocalServices.addService(AppStateTracker.class, mAppStateTracker);
        mUseMotionSensor = mInjector.useMotionSensor();
    }
+66 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.server;

import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Trace;

/**
 * Shared singleton background thread.
 *
 * @see com.android.internal.os.BackgroundThread
 */
public final class JobSchedulerBackgroundThread extends HandlerThread {
    private static final long SLOW_DISPATCH_THRESHOLD_MS = 10_000;
    private static final long SLOW_DELIVERY_THRESHOLD_MS = 30_000;
    private static JobSchedulerBackgroundThread sInstance;
    private static Handler sHandler;

    private JobSchedulerBackgroundThread() {
        super("jobscheduler.bg", android.os.Process.THREAD_PRIORITY_BACKGROUND);
    }

    private static void ensureThreadLocked() {
        if (sInstance == null) {
            sInstance = new JobSchedulerBackgroundThread();
            sInstance.start();
            final Looper looper = sInstance.getLooper();
            looper.setTraceTag(Trace.TRACE_TAG_SYSTEM_SERVER);
            looper.setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
            sHandler = new Handler(sInstance.getLooper());
        }
    }

    /** Returns the JobSchedulerBackgroundThread singleton */
    public static JobSchedulerBackgroundThread get() {
        synchronized (JobSchedulerBackgroundThread.class) {
            ensureThreadLocked();
            return sInstance;
        }
    }

    /** Returns the singleton handler for JobSchedulerBackgroundThread */
    public static Handler getHandler() {
        synchronized (JobSchedulerBackgroundThread.class) {
            ensureThreadLocked();
            return sHandler;
        }
    }
}
+2 −2
Original line number Diff line number Diff line
@@ -33,8 +33,8 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.procstats.ProcessStats;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.StatLogger;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.job.JobSchedulerService.Constants;
import com.android.server.job.JobSchedulerService.MaxJobCountsPerMemoryTrimLevel;
import com.android.server.job.controllers.JobStatus;
@@ -109,7 +109,7 @@ class JobConcurrencyManager {
        mConstants = service.mConstants;
        mContext = service.getContext();

        mHandler = BackgroundThread.getHandler();
        mHandler = JobSchedulerBackgroundThread.getHandler();
    }

    public void onSystemReady() {
+3 −2
Original line number Diff line number Diff line
@@ -87,7 +87,6 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.AppStateTracker;
import com.android.server.DeviceIdleInternal;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
import com.android.server.job.JobSchedulerServiceDumpProto.PendingJob;
@@ -1438,13 +1437,15 @@ public class JobSchedulerService extends com.android.server.SystemService

                    // And kick off the work to update the affected jobs, using a secondary
                    // thread instead of chugging away here on the main looper thread.
                    FgThread.getHandler().post(mJobTimeUpdater);
                    new Thread(mJobTimeUpdater, "JobSchedulerTimeSetReceiver").start();
                }
            }
        }
    };

    private final Runnable mJobTimeUpdater = () -> {
        Process.setThreadPriority(Process.THREAD_PRIORITY_FOREGROUND);

        final ArrayList<JobStatus> toRemove = new ArrayList<>();
        final ArrayList<JobStatus> toAdd = new ArrayList<>();
        synchronized (mLock) {
+3 −3
Original line number Diff line number Diff line
@@ -64,7 +64,7 @@ import android.util.proto.ProtoOutputStream;

import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.BackgroundThread;
import com.android.server.JobSchedulerBackgroundThread;
import com.android.server.LocalServices;
import com.android.server.job.ConstantsProto;
import com.android.server.job.JobSchedulerService;
@@ -1682,7 +1682,7 @@ public final class QuotaController extends StateController {
        public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId,
                boolean idle, int bucket, int reason) {
            // Update job bookkeeping out of band.
            BackgroundThread.getHandler().post(() -> {
            JobSchedulerBackgroundThread.getHandler().post(() -> {
                final int bucketIndex = JobSchedulerService.standbyBucketToBucketIndex(bucket);
                if (DEBUG) {
                    Slog.i(TAG, "Moving pkg " + string(userId, packageName) + " to bucketIndex "
@@ -2482,7 +2482,7 @@ public final class QuotaController extends StateController {

                if (changed) {
                    // Update job bookkeeping out of band.
                    BackgroundThread.getHandler().post(() -> {
                    JobSchedulerBackgroundThread.getHandler().post(() -> {
                        synchronized (mLock) {
                            invalidateAllExecutionStatsLocked();
                            maybeUpdateAllConstraintsLocked();