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

Commit e2ce2025 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Consolidate UserID+Package classes."

parents be127af0 c6a61948
Loading
Loading
Loading
Loading
+0 −59
Original line number Diff line number Diff line
/*
 * Copyright (C) 2021 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.job.controllers;

import java.util.Objects;

/** Wrapper class to represent a userId-pkgName combo. */
final class Package {
    public final String packageName;
    public final int userId;

    Package(int userId, String packageName) {
        this.userId = userId;
        this.packageName = packageName;
    }

    @Override
    public String toString() {
        return packageToString(userId, packageName);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Package)) {
            return false;
        }
        Package other = (Package) obj;
        return userId == other.userId && Objects.equals(packageName, other.packageName);
    }

    @Override
    public int hashCode() {
        return packageName.hashCode() + userId;
    }

    /**
     * Standardize the output of userId-packageName combo.
     */
    static String packageToString(int userId, String packageName) {
        return "<" + userId + ">" + packageName;
    }
}
+10 −10
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS;

import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.JobSchedulerService.sSystemClock;
import static com.android.server.job.controllers.Package.packageToString;

import android.annotation.CurrentTimeMillisLong;
import android.annotation.ElapsedRealtimeLong;
@@ -31,6 +30,7 @@ import android.app.usage.UsageStatsManagerInternal;
import android.app.usage.UsageStatsManagerInternal.EstimatedLaunchTimeChangedListener;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.pm.UserPackage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -172,7 +172,7 @@ public class PrefetchController extends StateController {
        final String pkgName = jobStatus.getSourcePackageName();
        final ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
        if (jobs != null && jobs.remove(jobStatus) && jobs.size() == 0) {
            mThresholdAlarmListener.removeAlarmForKey(new Package(userId, pkgName));
            mThresholdAlarmListener.removeAlarmForKey(UserPackage.of(userId, pkgName));
        }
    }

@@ -186,7 +186,7 @@ public class PrefetchController extends StateController {
        final int userId = UserHandle.getUserId(uid);
        mTrackedJobs.delete(userId, packageName);
        mEstimatedLaunchTimes.delete(userId, packageName);
        mThresholdAlarmListener.removeAlarmForKey(new Package(userId, packageName));
        mThresholdAlarmListener.removeAlarmForKey(UserPackage.of(userId, packageName));
    }

    @Override
@@ -354,7 +354,7 @@ public class PrefetchController extends StateController {
            @CurrentTimeMillisLong long now, @ElapsedRealtimeLong long nowElapsed) {
        final ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
        if (jobs == null || jobs.size() == 0) {
            mThresholdAlarmListener.removeAlarmForKey(new Package(userId, pkgName));
            mThresholdAlarmListener.removeAlarmForKey(UserPackage.of(userId, pkgName));
            return;
        }

@@ -365,10 +365,10 @@ public class PrefetchController extends StateController {
            // Set alarm to be notified when this crosses the threshold.
            final long timeToCrossThresholdMs =
                    nextEstimatedLaunchTime - (now + mLaunchTimeThresholdMs);
            mThresholdAlarmListener.addAlarm(new Package(userId, pkgName),
            mThresholdAlarmListener.addAlarm(UserPackage.of(userId, pkgName),
                    nowElapsed + timeToCrossThresholdMs);
        } else {
            mThresholdAlarmListener.removeAlarmForKey(new Package(userId, pkgName));
            mThresholdAlarmListener.removeAlarmForKey(UserPackage.of(userId, pkgName));
        }
    }

@@ -427,25 +427,25 @@ public class PrefetchController extends StateController {
    }

    /** Track when apps will cross the "will run soon" threshold. */
    private class ThresholdAlarmListener extends AlarmQueue<Package> {
    private class ThresholdAlarmListener extends AlarmQueue<UserPackage> {
        private ThresholdAlarmListener(Context context, Looper looper) {
            super(context, looper, "*job.prefetch*", "Prefetch threshold", false,
                    PcConstants.DEFAULT_LAUNCH_TIME_THRESHOLD_MS / 10);
        }

        @Override
        protected boolean isForUser(@NonNull Package key, int userId) {
        protected boolean isForUser(@NonNull UserPackage key, int userId) {
            return key.userId == userId;
        }

        @Override
        protected void processExpiredAlarms(@NonNull ArraySet<Package> expired) {
        protected void processExpiredAlarms(@NonNull ArraySet<UserPackage> expired) {
            final ArraySet<JobStatus> changedJobs = new ArraySet<>();
            synchronized (mLock) {
                final long now = sSystemClock.millis();
                final long nowElapsed = sElapsedRealtimeClock.millis();
                for (int i = 0; i < expired.size(); ++i) {
                    Package p = expired.valueAt(i);
                    UserPackage p = expired.valueAt(i);
                    if (!willBeLaunchedSoonLocked(p.userId, p.packageName, now)) {
                        Slog.e(TAG, "Alarm expired for "
                                + packageToString(p.userId, p.packageName) + " at the wrong time");
+20 −20
Original line number Diff line number Diff line
@@ -28,7 +28,6 @@ import static com.android.server.job.JobSchedulerService.RARE_INDEX;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.controllers.Package.packageToString;

import android.Manifest;
import android.annotation.NonNull;
@@ -44,6 +43,7 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.UserPackage;
import android.os.BatteryManager;
import android.os.Handler;
import android.os.Looper;
@@ -532,7 +532,7 @@ public final class QuotaController extends StateController {
     */
    private final SparseSetArray<String> mSystemInstallers = new SparseSetArray<>();

    /** An app has reached its quota. The message should contain a {@link Package} object. */
    /** An app has reached its quota. The message should contain a {@link UserPackage} object. */
    @VisibleForTesting
    static final int MSG_REACHED_QUOTA = 0;
    /** Drop any old timing sessions. */
@@ -542,7 +542,7 @@ public final class QuotaController extends StateController {
    /** Process state for a UID has changed. */
    private static final int MSG_UID_PROCESS_STATE_CHANGED = 3;
    /**
     * An app has reached its expedited job quota. The message should contain a {@link Package}
     * An app has reached its expedited job quota. The message should contain a {@link UserPackage}
     * object.
     */
    @VisibleForTesting
@@ -680,7 +680,7 @@ public final class QuotaController extends StateController {
            final String pkgName = jobStatus.getSourcePackageName();
            ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
            if (jobs != null && jobs.remove(jobStatus) && jobs.size() == 0) {
                mInQuotaAlarmQueue.removeAlarmForKey(new Package(userId, pkgName));
                mInQuotaAlarmQueue.removeAlarmForKey(UserPackage.of(userId, pkgName));
            }
        }
    }
@@ -746,7 +746,7 @@ public final class QuotaController extends StateController {
        }
        mTimingEvents.delete(userId, packageName);
        mEJTimingSessions.delete(userId, packageName);
        mInQuotaAlarmQueue.removeAlarmForKey(new Package(userId, packageName));
        mInQuotaAlarmQueue.removeAlarmForKey(UserPackage.of(userId, packageName));
        mExecutionStatsCache.delete(userId, packageName);
        mEJStats.delete(userId, packageName);
        mTopAppTrackers.delete(userId, packageName);
@@ -1725,7 +1725,7 @@ public final class QuotaController extends StateController {
            // exempted.
            maybeScheduleStartAlarmLocked(userId, packageName, realStandbyBucket);
        } else {
            mInQuotaAlarmQueue.removeAlarmForKey(new Package(userId, packageName));
            mInQuotaAlarmQueue.removeAlarmForKey(UserPackage.of(userId, packageName));
        }
        return changedJobs;
    }
@@ -1764,7 +1764,7 @@ public final class QuotaController extends StateController {
                    && isWithinQuotaLocked(userId, packageName, realStandbyBucket)) {
                // TODO(141645789): we probably shouldn't cancel the alarm until we've verified
                // that all jobs for the userId-package are within quota.
                mInQuotaAlarmQueue.removeAlarmForKey(new Package(userId, packageName));
                mInQuotaAlarmQueue.removeAlarmForKey(UserPackage.of(userId, packageName));
            } else {
                mToScheduleStartAlarms.add(userId, packageName, realStandbyBucket);
            }
@@ -1814,7 +1814,7 @@ public final class QuotaController extends StateController {
        if (jobs == null || jobs.size() == 0) {
            Slog.e(TAG, "maybeScheduleStartAlarmLocked called for "
                    + packageToString(userId, packageName) + " that has no jobs");
            mInQuotaAlarmQueue.removeAlarmForKey(new Package(userId, packageName));
            mInQuotaAlarmQueue.removeAlarmForKey(UserPackage.of(userId, packageName));
            return;
        }

@@ -1838,7 +1838,7 @@ public final class QuotaController extends StateController {
                        + getRemainingExecutionTimeLocked(userId, packageName, standbyBucket)
                        + "ms in its quota.");
            }
            mInQuotaAlarmQueue.removeAlarmForKey(new Package(userId, packageName));
            mInQuotaAlarmQueue.removeAlarmForKey(UserPackage.of(userId, packageName));
            mHandler.obtainMessage(MSG_CHECK_PACKAGE, userId, 0, packageName).sendToTarget();
            return;
        }
@@ -1903,7 +1903,7 @@ public final class QuotaController extends StateController {
                            + nowElapsed + ", inQuotaTime=" + inQuotaTimeElapsed + ": " + stats);
            inQuotaTimeElapsed = nowElapsed + 5 * MINUTE_IN_MILLIS;
        }
        mInQuotaAlarmQueue.addAlarm(new Package(userId, packageName), inQuotaTimeElapsed);
        mInQuotaAlarmQueue.addAlarm(UserPackage.of(userId, packageName), inQuotaTimeElapsed);
    }

    private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, long nowElapsed,
@@ -2098,7 +2098,7 @@ public final class QuotaController extends StateController {
    }

    private final class Timer {
        private final Package mPkg;
        private final UserPackage mPkg;
        private final int mUid;
        private final boolean mRegularJobTimer;

@@ -2110,7 +2110,7 @@ public final class QuotaController extends StateController {
        private long mDebitAdjustment;

        Timer(int uid, int userId, String packageName, boolean regularJobTimer) {
            mPkg = new Package(userId, packageName);
            mPkg = UserPackage.of(userId, packageName);
            mUid = uid;
            mRegularJobTimer = regularJobTimer;
        }
@@ -2365,7 +2365,7 @@ public final class QuotaController extends StateController {
    }

    private final class TopAppTimer {
        private final Package mPkg;
        private final UserPackage mPkg;

        // List of jobs currently running for this app that started when the app wasn't in the
        // foreground.
@@ -2373,7 +2373,7 @@ public final class QuotaController extends StateController {
        private long mStartTimeElapsed;

        TopAppTimer(int userId, String packageName) {
            mPkg = new Package(userId, packageName);
            mPkg = UserPackage.of(userId, packageName);
        }

        private int calculateTimeChunks(final long nowElapsed) {
@@ -2656,7 +2656,7 @@ public final class QuotaController extends StateController {
            synchronized (mLock) {
                switch (msg.what) {
                    case MSG_REACHED_QUOTA: {
                        Package pkg = (Package) msg.obj;
                        UserPackage pkg = (UserPackage) msg.obj;
                        if (DEBUG) {
                            Slog.d(TAG, "Checking if " + pkg + " has reached its quota.");
                        }
@@ -2685,7 +2685,7 @@ public final class QuotaController extends StateController {
                        break;
                    }
                    case MSG_REACHED_EJ_QUOTA: {
                        Package pkg = (Package) msg.obj;
                        UserPackage pkg = (UserPackage) msg.obj;
                        if (DEBUG) {
                            Slog.d(TAG, "Checking if " + pkg + " has reached its EJ quota.");
                        }
@@ -2887,21 +2887,21 @@ public final class QuotaController extends StateController {
    }

    /** Track when UPTCs are expected to come back into quota. */
    private class InQuotaAlarmQueue extends AlarmQueue<Package> {
    private class InQuotaAlarmQueue extends AlarmQueue<UserPackage> {
        private InQuotaAlarmQueue(Context context, Looper looper) {
            super(context, looper, ALARM_TAG_QUOTA_CHECK, "In quota", false,
                    QcConstants.DEFAULT_MIN_QUOTA_CHECK_DELAY_MS);
        }

        @Override
        protected boolean isForUser(@NonNull Package key, int userId) {
        protected boolean isForUser(@NonNull UserPackage key, int userId) {
            return key.userId == userId;
        }

        @Override
        protected void processExpiredAlarms(@NonNull ArraySet<Package> expired) {
        protected void processExpiredAlarms(@NonNull ArraySet<UserPackage> expired) {
            for (int i = 0; i < expired.size(); ++i) {
                Package p = expired.valueAt(i);
                UserPackage p = expired.valueAt(i);
                mHandler.obtainMessage(MSG_CHECK_PACKAGE, p.userId, 0, p.packageName)
                        .sendToTarget();
            }
+7 −0
Original line number Diff line number Diff line
@@ -186,4 +186,11 @@ public abstract class StateController {
    /** Dump any internal constants the Controller may have. */
    public void dumpConstants(ProtoOutputStream proto) {
    }

    /**
     * Standardize the output of userId-packageName combo.
     */
    static String packageToString(int userId, String packageName) {
        return "<" + userId + ">" + packageName;
    }
}
+9 −43
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import static com.android.server.tare.TareUtils.getCurrentTimeMillis;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.UserPackage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -824,7 +825,7 @@ class Agent {
    void onPackageRemovedLocked(final int userId, @NonNull final String pkgName) {
        mScribe.discardLedgerLocked(userId, pkgName);
        mCurrentOngoingEvents.delete(userId, pkgName);
        mBalanceThresholdAlarmQueue.removeAlarmForKey(new Package(userId, pkgName));
        mBalanceThresholdAlarmQueue.removeAlarmForKey(UserPackage.of(userId, pkgName));
    }

    @GuardedBy("mLock")
@@ -959,7 +960,7 @@ class Agent {
                mCurrentOngoingEvents.get(userId, pkgName);
        if (ongoingEvents == null || mIrs.isVip(userId, pkgName)) {
            // No ongoing transactions. No reason to schedule
            mBalanceThresholdAlarmQueue.removeAlarmForKey(new Package(userId, pkgName));
            mBalanceThresholdAlarmQueue.removeAlarmForKey(UserPackage.of(userId, pkgName));
            return;
        }
        mTrendCalculator.reset(getBalanceLocked(userId, pkgName),
@@ -972,7 +973,7 @@ class Agent {
        if (lowerTimeMs == TrendCalculator.WILL_NOT_CROSS_THRESHOLD) {
            if (upperTimeMs == TrendCalculator.WILL_NOT_CROSS_THRESHOLD) {
                // Will never cross a threshold based on current events.
                mBalanceThresholdAlarmQueue.removeAlarmForKey(new Package(userId, pkgName));
                mBalanceThresholdAlarmQueue.removeAlarmForKey(UserPackage.of(userId, pkgName));
                return;
            }
            timeToThresholdMs = upperTimeMs;
@@ -980,7 +981,7 @@ class Agent {
            timeToThresholdMs = (upperTimeMs == TrendCalculator.WILL_NOT_CROSS_THRESHOLD)
                    ? lowerTimeMs : Math.min(lowerTimeMs, upperTimeMs);
        }
        mBalanceThresholdAlarmQueue.addAlarm(new Package(userId, pkgName),
        mBalanceThresholdAlarmQueue.addAlarm(UserPackage.of(userId, pkgName),
                SystemClock.elapsedRealtime() + timeToThresholdMs);
    }

@@ -1071,57 +1072,22 @@ class Agent {

    private final OngoingEventUpdater mOngoingEventUpdater = new OngoingEventUpdater();

    private static final class Package {
        public final String packageName;
        public final int userId;

        Package(int userId, String packageName) {
            this.userId = userId;
            this.packageName = packageName;
        }

        @Override
        public String toString() {
            return appToString(userId, packageName);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (this == obj) {
                return true;
            }
            if (obj instanceof Package) {
                Package other = (Package) obj;
                return userId == other.userId && Objects.equals(packageName, other.packageName);
            }
            return false;
        }

        @Override
        public int hashCode() {
            return packageName.hashCode() + userId;
        }
    }

    /** Track when apps will cross the closest affordability threshold (in both directions). */
    private class BalanceThresholdAlarmQueue extends AlarmQueue<Package> {
    private class BalanceThresholdAlarmQueue extends AlarmQueue<UserPackage> {
        private BalanceThresholdAlarmQueue(Context context, Looper looper) {
            super(context, looper, ALARM_TAG_AFFORDABILITY_CHECK, "Affordability check", true,
                    15_000L);
        }

        @Override
        protected boolean isForUser(@NonNull Package key, int userId) {
        protected boolean isForUser(@NonNull UserPackage key, int userId) {
            return key.userId == userId;
        }

        @Override
        protected void processExpiredAlarms(@NonNull ArraySet<Package> expired) {
        protected void processExpiredAlarms(@NonNull ArraySet<UserPackage> expired) {
            for (int i = 0; i < expired.size(); ++i) {
                Package p = expired.valueAt(i);
                UserPackage p = expired.valueAt(i);
                mHandler.obtainMessage(
                        MSG_CHECK_INDIVIDUAL_AFFORDABILITY, p.userId, 0, p.packageName)
                        .sendToTarget();
Loading