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

Commit f6cfdb56 authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 7343210 from c5535ff0 to sc-release

Change-Id: Ia84255ff85693d7c7eb4035ff1177111f7be5ef4
parents 22a3af24 c5535ff0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -326,6 +326,7 @@ java_defaults {
        "tv_tuner_resource_manager_aidl_interface-java",
        "soundtrigger_middleware-aidl-java",
        "modules-utils-os",
        "framework-permission-aidl-java",
    ],
}

+24 −1
Original line number Diff line number Diff line
@@ -236,7 +236,21 @@ public class PowerExemptionManager {
     * @hide
     */
    public static final int REASON_BLUETOOTH_BROADCAST = 203;

    /**
     * Broadcast {@link android.content.Intent#ACTION_TIMEZONE_CHANGED}
     * @hide
     */
    public static final int REASON_TIMEZONE_CHANGED = 204;
    /**
     * Broadcast {@link android.content.Intent#ACTION_TIME_CHANGED}
     * @hide
     */
    public static final int REASON_TIME_CHANGED = 205;
    /**
     * Broadcast {@link android.content.Intent#ACTION_LOCALE_CHANGED}
     * @hide
     */
    public static final int REASON_LOCALE_CHANGED = 206;
    /* Reason code range 300-399 are reserved for other internal reasons */
    /**
     * Device idle system allow list, including EXCEPT-IDLE
@@ -369,6 +383,9 @@ public class PowerExemptionManager {
            REASON_PRE_BOOT_COMPLETED,
            REASON_LOCKED_BOOT_COMPLETED,
            REASON_BLUETOOTH_BROADCAST,
            REASON_TIMEZONE_CHANGED,
            REASON_TIME_CHANGED,
            REASON_LOCALE_CHANGED,
            REASON_SYSTEM_ALLOW_LISTED,
            REASON_ALARM_MANAGER_ALARM_CLOCK,
            REASON_ALARM_MANAGER_WHILE_IDLE,
@@ -641,6 +658,12 @@ public class PowerExemptionManager {
                return "LOCKED_BOOT_COMPLETED";
            case REASON_BLUETOOTH_BROADCAST:
                return "BLUETOOTH_BROADCAST";
            case REASON_TIMEZONE_CHANGED:
                return "TIMEZONE_CHANGED";
            case REASON_TIME_CHANGED:
                return "TIME_CHANGED";
            case REASON_LOCALE_CHANGED:
                return "LOCALE_CHANGED";
            case REASON_SYSTEM_ALLOW_LISTED:
                return "SYSTEM_ALLOW_LISTED";
            case REASON_ALARM_MANAGER_ALARM_CLOCK:
+26 −6
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import static android.app.AlarmManager.INTERVAL_HOUR;
import static android.app.AlarmManager.RTC;
import static android.app.AlarmManager.RTC_WAKEUP;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
import static android.os.PowerExemptionManager.TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
import static android.os.PowerWhitelistManager.REASON_ALARM_MANAGER_WHILE_IDLE;
import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED;
import static android.os.PowerWhitelistManager.TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_NOT_ALLOWED;
@@ -81,6 +82,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelableException;
import android.os.PowerExemptionManager;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
@@ -118,6 +120,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.os.BinderDeathDispatcher;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.LocalLog;
@@ -202,6 +205,8 @@ public class AlarmManagerService extends SystemService {
                    .addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
                            | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);

    private static final BinderDeathDispatcher<IAlarmListener> sListenerDeathDispatcher =
            new BinderDeathDispatcher<>();
    final LocalLog mLog = new LocalLog(TAG);

    AppOpsManager mAppOps;
@@ -292,6 +297,7 @@ public class AlarmManagerService extends SystemService {

    BroadcastOptions mOptsWithFgs = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsWithoutFgs = BroadcastOptions.makeBasic();
    BroadcastOptions mOptsTimeBroadcast = BroadcastOptions.makeBasic();

    // TODO(b/172085676): Move inside alarm store.
    private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
@@ -1786,7 +1792,12 @@ public class AlarmManagerService extends SystemService {
                    | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                    | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
            intent.putExtra(Intent.EXTRA_TIMEZONE, zone.getID());
            getContext().sendBroadcastAsUser(intent, UserHandle.ALL);
            mOptsTimeBroadcast.setTemporaryAppAllowlist(
                    mActivityManagerInternal.getBootTimeTempAllowListDuration(),
                    TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                    PowerExemptionManager.REASON_TIMEZONE_CHANGED, "");
            getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
                    null /* receiverPermission */, mOptsTimeBroadcast.toBundle());
        }
    }

@@ -1809,9 +1820,8 @@ public class AlarmManagerService extends SystemService {
        }

        if (directReceiver != null) {
            try {
                directReceiver.asBinder().linkToDeath(mListenerDeathRecipient, 0);
            } catch (RemoteException e) {
            if (sListenerDeathDispatcher.linkToDeath(directReceiver, mListenerDeathRecipient)
                    <= 0) {
                Slog.w(TAG, "Dropping unreachable alarm listener " + listenerTag);
                return;
            }
@@ -2824,6 +2834,12 @@ public class AlarmManagerService extends SystemService {
                pw.println();
            }

            pw.println("Listener death dispatcher state:");
            pw.increaseIndent();
            sListenerDeathDispatcher.dump(pw);
            pw.println();
            pw.decreaseIndent();

            if (mLog.dump(pw, "Recent problems:")) {
                pw.println();
            }
@@ -3929,8 +3945,12 @@ public class AlarmManagerService extends SystemService {
                                | Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
                                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
                                | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
                        getContext().sendBroadcastAsUser(intent, UserHandle.ALL);

                        mOptsTimeBroadcast.setTemporaryAppAllowlist(
                                mActivityManagerInternal.getBootTimeTempAllowListDuration(),
                                TEMPORARY_ALLOW_LIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
                                PowerExemptionManager.REASON_TIME_CHANGED, "");
                        getContext().sendBroadcastAsUser(intent, UserHandle.ALL,
                                null /* receiverPermission */, mOptsTimeBroadcast.toBundle());
                        // The world has changed on us, so we need to re-evaluate alarms
                        // regardless of whether the kernel has told us one went off.
                        result |= IS_WAKEUP_MASK;
+52 −66
Original line number Diff line number Diff line
@@ -621,6 +621,7 @@ public final class QuotaController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
        final long nowElapsed = sElapsedRealtimeClock.millis();
        final int userId = jobStatus.getSourceUserId();
@@ -648,6 +649,7 @@ public final class QuotaController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void prepareForExecutionLocked(JobStatus jobStatus) {
        if (DEBUG) {
            Slog.d(TAG, "Prepping for " + jobStatus.toShortString());
@@ -676,6 +678,7 @@ public final class QuotaController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void unprepareFromExecutionLocked(JobStatus jobStatus) {
        Timer timer = mPkgTimers.get(jobStatus.getSourceUserId(), jobStatus.getSourcePackageName());
        if (timer != null) {
@@ -691,6 +694,7 @@ public final class QuotaController extends StateController {
    }

    @Override
    @GuardedBy("mLock")
    public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
            boolean forUpdate) {
        if (jobStatus.clearTrackingController(JobStatus.TRACKING_QUOTA)) {
@@ -796,10 +800,12 @@ public final class QuotaController extends StateController {
    }

    /** Returns the maximum amount of time this job could run for. */
    @GuardedBy("mLock")
    public long getMaxJobExecutionTimeMsLocked(@NonNull final JobStatus jobStatus) {
        if (!jobStatus.shouldTreatAsExpeditedJob()) {
            // If quota is currently "free", then the job can run for the full amount of time.
            if (mChargeTracker.isCharging()
            // If quota is currently "free", then the job can run for the full amount of time,
            // regardless of bucket (hence using charging instead of isQuotaFreeLocked()).
            if (mChargeTracker.isChargingLocked()
                    || mTopAppCache.get(jobStatus.getSourceUid())
                    || isTopStartedJobLocked(jobStatus)
                    || isUidInForeground(jobStatus.getSourceUid())) {
@@ -810,7 +816,7 @@ public final class QuotaController extends StateController {
        }

        // Expedited job.
        if (mChargeTracker.isCharging()) {
        if (mChargeTracker.isChargingLocked()) {
            return mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
        }
        if (mTopAppCache.get(jobStatus.getSourceUid()) || isTopStartedJobLocked(jobStatus)) {
@@ -828,8 +834,9 @@ public final class QuotaController extends StateController {
    }

    /** @return true if the job is within expedited job quota. */
    @GuardedBy("mLock")
    public boolean isWithinEJQuotaLocked(@NonNull final JobStatus jobStatus) {
        if (isQuotaFree(jobStatus.getEffectiveStandbyBucket())) {
        if (isQuotaFreeLocked(jobStatus.getEffectiveStandbyBucket())) {
            return true;
        }
        // A job is within quota if one of the following is true:
@@ -887,9 +894,10 @@ public final class QuotaController extends StateController {
                jobStatus.getSourceUserId(), jobStatus.getSourcePackageName(), standbyBucket);
    }

    private boolean isQuotaFree(final int standbyBucket) {
    @GuardedBy("mLock")
    private boolean isQuotaFreeLocked(final int standbyBucket) {
        // Quota constraint is not enforced while charging.
        if (mChargeTracker.isCharging()) {
        if (mChargeTracker.isChargingLocked()) {
            // Restricted jobs require additional constraints when charging, so don't immediately
            // mark quota as free when charging.
            return standbyBucket != RESTRICTED_INDEX;
@@ -898,11 +906,12 @@ public final class QuotaController extends StateController {
    }

    @VisibleForTesting
    @GuardedBy("mLock")
    boolean isWithinQuotaLocked(final int userId, @NonNull final String packageName,
            final int standbyBucket) {
        if (standbyBucket == NEVER_INDEX) return false;

        if (isQuotaFree(standbyBucket)) return true;
        if (isQuotaFreeLocked(standbyBucket)) return true;

        ExecutionStats stats = getExecutionStatsLocked(userId, packageName, standbyBucket);
        return getRemainingExecutionTimeLocked(stats) > 0
@@ -1493,14 +1502,13 @@ public final class QuotaController extends StateController {
    /** Schedule a cleanup alarm if necessary and there isn't already one scheduled. */
    @VisibleForTesting
    void maybeScheduleCleanupAlarmLocked() {
        final long nowElapsed = sElapsedRealtimeClock.millis();
        if (mNextCleanupTimeElapsed > nowElapsed) {
        if (mNextCleanupTimeElapsed > sElapsedRealtimeClock.millis()) {
            // There's already an alarm scheduled. Just stick with that one. There's no way we'll
            // end up scheduling an earlier alarm.
            if (DEBUG) {
                Slog.v(TAG, "Not scheduling cleanup since there's already one at "
                        + mNextCleanupTimeElapsed
                        + " (in " + (mNextCleanupTimeElapsed - nowElapsed) + "ms)");
                        + mNextCleanupTimeElapsed + " (in " + (mNextCleanupTimeElapsed
                        - sElapsedRealtimeClock.millis()) + "ms)");
            }
            return;
        }
@@ -1522,7 +1530,7 @@ public final class QuotaController extends StateController {
        if (nextCleanupElapsed - mNextCleanupTimeElapsed <= 10 * MINUTE_IN_MILLIS) {
            // No need to clean up too often. Delay the alarm if the next cleanup would be too soon
            // after it.
            nextCleanupElapsed = mNextCleanupTimeElapsed + 10 * MINUTE_IN_MILLIS;
            nextCleanupElapsed += 10 * MINUTE_IN_MILLIS;
        }
        mNextCleanupTimeElapsed = nextCleanupElapsed;
        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, nextCleanupElapsed, ALARM_TAG_CLEANUP,
@@ -1557,9 +1565,9 @@ public final class QuotaController extends StateController {

    private void handleNewChargingStateLocked() {
        mTimerChargingUpdateFunctor.setStatus(sElapsedRealtimeClock.millis(),
                mChargeTracker.isCharging());
                mChargeTracker.isChargingLocked());
        if (DEBUG) {
            Slog.d(TAG, "handleNewChargingStateLocked: " + mChargeTracker.isCharging());
            Slog.d(TAG, "handleNewChargingStateLocked: " + mChargeTracker.isChargingLocked());
        }
        // Deal with Timers first.
        mEJPkgTimers.forEach(mTimerChargingUpdateFunctor);
@@ -1828,6 +1836,7 @@ public final class QuotaController extends StateController {
         * Track whether we're charging. This has a slightly different definition than that of
         * BatteryController.
         */
        @GuardedBy("mLock")
        private boolean mCharging;

        ChargingTracker() {
@@ -1847,7 +1856,8 @@ public final class QuotaController extends StateController {
            mCharging = batteryManagerInternal.isPowered(BatteryManager.BATTERY_PLUGGED_ANY);
        }

        public boolean isCharging() {
        @GuardedBy("mLock")
        public boolean isChargingLocked() {
            return mCharging;
        }

@@ -2056,9 +2066,12 @@ public final class QuotaController extends StateController {
                    }
                    return;
                }
                if (mRunningBgJobs.remove(jobStatus)
                        && !mChargeTracker.isCharging() && mRunningBgJobs.size() == 0) {
                    emitSessionLocked(sElapsedRealtimeClock.millis());
                final long nowElapsed = sElapsedRealtimeClock.millis();
                final int standbyBucket = JobSchedulerService.standbyBucketForPackage(
                        mPkg.packageName, mPkg.userId, nowElapsed);
                if (mRunningBgJobs.remove(jobStatus) && mRunningBgJobs.size() == 0
                        && !isQuotaFreeLocked(standbyBucket)) {
                    emitSessionLocked(nowElapsed);
                    cancelCutoff();
                }
            }
@@ -2078,6 +2091,7 @@ public final class QuotaController extends StateController {
            cancelCutoff();
        }

        @GuardedBy("mLock")
        private void emitSessionLocked(long nowElapsed) {
            if (mBgJobCount <= 0) {
                // Nothing to emit.
@@ -2122,6 +2136,7 @@ public final class QuotaController extends StateController {
            }
        }

        @GuardedBy("mLock")
        private boolean shouldTrackLocked() {
            final long nowElapsed = sElapsedRealtimeClock.millis();
            final int standbyBucket = JobSchedulerService.standbyBucketForPackage(mPkg.packageName,
@@ -2133,7 +2148,7 @@ public final class QuotaController extends StateController {
            final long topAppGracePeriodEndElapsed = mTopAppGraceCache.get(mUid);
            final boolean hasTopAppExemption = !mRegularJobTimer
                    && (mTopAppCache.get(mUid) || nowElapsed < topAppGracePeriodEndElapsed);
            return (standbyBucket == RESTRICTED_INDEX || !mChargeTracker.isCharging())
            return !isQuotaFreeLocked(standbyBucket)
                    && !mForegroundUids.get(mUid) && !hasTempAllowlistExemption
                    && !hasTopAppExemption;
        }
@@ -2463,60 +2478,30 @@ public final class QuotaController extends StateController {
        }
    }

    private static final class TimingSessionTooOldPredicate implements Predicate<TimingSession> {
        private long mNowElapsed;

        private void updateNow() {
            mNowElapsed = sElapsedRealtimeClock.millis();
        }

        @Override
    private final class DeleteTimingSessionsFunctor implements Consumer<List<TimingSession>> {
        private final Predicate<TimingSession> mTooOld = new Predicate<TimingSession>() {
            public boolean test(TimingSession ts) {
            return ts.endTimeElapsed <= mNowElapsed - MAX_PERIOD_MS;
        }
                return ts.endTimeElapsed <= sElapsedRealtimeClock.millis() - MAX_PERIOD_MS;
            }
        };

    private final TimingSessionTooOldPredicate mTimingSessionTooOld =
            new TimingSessionTooOldPredicate();

    private final Consumer<List<TimingSession>> mDeleteOldSessionsFunctor = sessions -> {
        @Override
        public void accept(List<TimingSession> sessions) {
            if (sessions != null) {
                // Remove everything older than MAX_PERIOD_MS time ago.
            sessions.removeIf(mTimingSessionTooOld);
                sessions.removeIf(mTooOld);
            }
    };
        }
    }

    private final DeleteTimingSessionsFunctor mDeleteOldSessionsFunctor =
            new DeleteTimingSessionsFunctor();

    @VisibleForTesting
    void deleteObsoleteSessionsLocked() {
        mTimingSessionTooOld.updateNow();

        // Regular sessions
        mTimingSessions.forEach(mDeleteOldSessionsFunctor);

        // EJ sessions
        for (int uIdx = 0; uIdx < mEJTimingSessions.numMaps(); ++uIdx) {
            final int userId = mEJTimingSessions.keyAt(uIdx);
            for (int pIdx = 0; pIdx < mEJTimingSessions.numElementsForKey(userId); ++pIdx) {
                final String packageName = mEJTimingSessions.keyAt(uIdx, pIdx);
                final ShrinkableDebits debits = getEJDebitsLocked(userId, packageName);
                final List<TimingSession> sessions = mEJTimingSessions.get(userId, packageName);
                if (sessions == null) {
                    continue;
                }

                while (sessions.size() > 0) {
                    final TimingSession ts = sessions.get(0);
                    if (mTimingSessionTooOld.test(ts)) {
                        // Stale sessions may still be factored into tally. Remove them.
                        final long duration = ts.endTimeElapsed - ts.startTimeElapsed;
                        debits.transactLocked(-duration);
                        sessions.remove(0);
                    } else {
                        break;
                    }
                }
            }
        }
        // Don't delete EJ timing sessions here. They'll be removed in
        // getRemainingEJExecutionTimeLocked().
    }

    private class QcHandler extends Handler {
@@ -4085,7 +4070,7 @@ public final class QuotaController extends StateController {
    @Override
    public void dumpControllerStateLocked(final IndentingPrintWriter pw,
            final Predicate<JobStatus> predicate) {
        pw.println("Is charging: " + mChargeTracker.isCharging());
        pw.println("Is charging: " + mChargeTracker.isChargingLocked());
        pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis());
        pw.println();

@@ -4262,7 +4247,8 @@ public final class QuotaController extends StateController {
        final long token = proto.start(fieldId);
        final long mToken = proto.start(StateControllerProto.QUOTA);

        proto.write(StateControllerProto.QuotaController.IS_CHARGING, mChargeTracker.isCharging());
        proto.write(StateControllerProto.QuotaController.IS_CHARGING,
                mChargeTracker.isChargingLocked());
        proto.write(StateControllerProto.QuotaController.ELAPSED_REALTIME,
                sElapsedRealtimeClock.millis());

+3 −3
Original line number Diff line number Diff line
@@ -56,7 +56,7 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id
    private boolean mDockIdle;
    private boolean mProjectionActive;
    private IdlenessListener mIdleListener;
    private final UiModeManager.OnProjectionStateChangeListener mOnProjectionStateChangeListener =
    private final UiModeManager.OnProjectionStateChangedListener mOnProjectionStateChangedListener =
            this::onProjectionStateChanged;

    private AlarmManager.OnAlarmListener mIdleAlarmListener = () -> {
@@ -105,9 +105,9 @@ public final class DeviceIdlenessTracker extends BroadcastReceiver implements Id

        // TODO(b/172579710): Move the callbacks off the main executor and on to
        //  JobSchedulerBackgroundThread.getExecutor() once synchronization is fixed in this class.
        context.getSystemService(UiModeManager.class).addOnProjectionStateChangeListener(
        context.getSystemService(UiModeManager.class).addOnProjectionStateChangedListener(
                UiModeManager.PROJECTION_TYPE_ALL, context.getMainExecutor(),
                mOnProjectionStateChangeListener);
                mOnProjectionStateChangedListener);
    }

    private void onProjectionStateChanged(@UiModeManager.ProjectionType int activeProjectionTypes,
Loading