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

Commit dc27292b authored by Jing Ji's avatar Jing Ji Committed by Android (Google) Code Review
Browse files

Merge "Don't auto move into restricted bucket if there's a recent interaction" into tm-dev

parents ec1e2907 d576379b
Loading
Loading
Loading
Loading
+92 −14
Original line number Diff line number Diff line
@@ -67,6 +67,7 @@ import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseLongArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;

@@ -360,6 +361,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                    mUidBatteryUsageInWindow.removeAt(i);
                }
            }
            mInjector.getPolicy().onUserRemovedLocked(userId);
        }
    }

@@ -368,6 +370,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
        synchronized (mLock) {
            mUidBatteryUsage.delete(uid);
            mUidBatteryUsageInWindow.delete(uid);
            mInjector.getPolicy().onUidRemovedLocked(uid);
        }
    }

@@ -1207,6 +1210,14 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
        static final String KEY_BG_CURRENT_DRAIN_WINDOW =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "current_drain_window";

        /**
         * The grace period after an interaction event with the app, if the background current
         * drain goes beyond the threshold within that period, the system won't apply the
         * restrictions.
         */
        static final String KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD =
                DEVICE_CONFIG_SUBNAMESPACE_PREFIX + "current_drain_interaction_grace_period";

        /**
         * Similar to {@link #KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET}, but a higher
         * value for the legitimate cases with higher background current drain.
@@ -1309,6 +1320,11 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
         */
        final long mDefaultBgCurrentDrainWindowMs;

        /**
         * Default value to {@link #mBgCurrentDrainInteractionGracePeriodMs}.
         */
        final long mDefaultBgCurrentDrainInteractionGracePeriodMs;

        /**
         * Default value to the {@link #INDEX_HIGH_CURRENT_DRAIN_THRESHOLD} of
         * the {@link #mBgCurrentDrainRestrictedBucketThreshold}.
@@ -1393,6 +1409,11 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
         */
        volatile long mBgCurrentDrainWindowMs;

        /**
         * @see #KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD.
         */
        volatile long mBgCurrentDrainInteractionGracePeriodMs;

        /**
         * @see #KEY_BG_CURRENT_DRAIN_MEDIA_PLAYBACK_MIN_DURATION.
         */
@@ -1455,6 +1476,12 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
        private final SparseArray<Pair<long[], ImmutableBatteryUsage[]>> mHighBgBatteryPackages =
                new SparseArray<>();

        /**
         * The timestamp of the last interaction, key is the UID.
         */
        @GuardedBy("mLock")
        private final SparseLongArray mLastInteractionTime = new SparseLongArray();

        @NonNull
        private final Object mLock;

@@ -1478,6 +1505,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                    isLowRamDeviceStatic() ? val[1] : val[0];
            mDefaultBgCurrentDrainWindowMs = resources.getInteger(
                    R.integer.config_bg_current_drain_window) * 1_000;
            mDefaultBgCurrentDrainInteractionGracePeriodMs = mDefaultBgCurrentDrainWindowMs;
            val = getFloatArray(resources.obtainTypedArray(
                    R.array.config_bg_current_drain_high_threshold_to_restricted_bucket));
            mDefaultBgCurrentDrainRestrictedBucketHighThreshold =
@@ -1511,6 +1539,8 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
            mBgCurrentDrainBgRestrictedThreshold[1] =
                    mDefaultBgCurrentDrainBgRestrictedHighThreshold;
            mBgCurrentDrainWindowMs = mDefaultBgCurrentDrainWindowMs;
            mBgCurrentDrainInteractionGracePeriodMs =
                    mDefaultBgCurrentDrainInteractionGracePeriodMs;
            mBgCurrentDrainMediaPlaybackMinDuration =
                    mDefaultBgCurrentDrainMediaPlaybackMinDuration;
            mBgCurrentDrainLocationMinDuration = mDefaultBgCurrentDrainLocationMinDuration;
@@ -1542,6 +1572,9 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                case KEY_BG_CURRENT_DRAIN_WINDOW:
                    updateCurrentDrainWindow();
                    break;
                case KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD:
                    updateCurrentDrainInteractionGracePeriod();
                    break;
                case KEY_BG_CURRENT_DRAIN_MEDIA_PLAYBACK_MIN_DURATION:
                    updateCurrentDrainMediaPlaybackMinDuration();
                    break;
@@ -1626,6 +1659,13 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                    mDefaultBgCurrentDrainWindowMs);
        }

        private void updateCurrentDrainInteractionGracePeriod() {
            mBgCurrentDrainInteractionGracePeriodMs = DeviceConfig.getLong(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD,
                    mDefaultBgCurrentDrainInteractionGracePeriodMs);
        }

        private void updateCurrentDrainMediaPlaybackMinDuration() {
            mBgCurrentDrainMediaPlaybackMinDuration = DeviceConfig.getLong(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -1668,6 +1708,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
            super.onSystemReady();
            updateCurrentDrainThreshold();
            updateCurrentDrainWindow();
            updateCurrentDrainInteractionGracePeriod();
            updateCurrentDrainMediaPlaybackMinDuration();
            updateCurrentDrainLocationMinDuration();
            updateCurrentDrainEventDurationBasedThresholdEnabled();
@@ -1685,8 +1726,10 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
            synchronized (mLock) {
                final Pair<long[], ImmutableBatteryUsage[]> pair = mHighBgBatteryPackages.get(uid);
                if (pair != null) {
                    final long lastInteractionTime = mLastInteractionTime.get(uid, 0L);
                    final long[] ts = pair.first;
                    final int restrictedLevel = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] > 0
                    final int restrictedLevel = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET]
                            > (lastInteractionTime + mBgCurrentDrainInteractionGracePeriodMs)
                            && mTracker.mAppRestrictionController.isAutoRestrictAbusiveAppEnabled()
                            ? RESTRICTION_LEVEL_RESTRICTED_BUCKET
                            : RESTRICTION_LEVEL_ADAPTIVE_BUCKET;
@@ -1777,6 +1820,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                    // We're already in the background restricted level, nothing more we could do.
                    return;
                }
                final long lastInteractionTime = mLastInteractionTime.get(uid, 0L);
                final long now = SystemClock.elapsedRealtime();
                final int thresholdIndex = getCurrentDrainThresholdIndex(uid, now,
                        mBgCurrentDrainWindowMs);
@@ -1788,13 +1832,17 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                    long[] ts = null;
                    ImmutableBatteryUsage[] usages = null;
                    if (rbPercentage >= rbThreshold) {
                        if (now > lastInteractionTime + mBgCurrentDrainInteractionGracePeriodMs) {
                            // New findings to us, track it and let the controller know.
                            ts = new long[TIME_STAMP_INDEX_LAST];
                            ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
                            usages = new ImmutableBatteryUsage[TIME_STAMP_INDEX_LAST];
                            usages[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
                            mHighBgBatteryPackages.put(uid, Pair.create(ts, usages));
                        notifyController = excessive = true;
                            // It's beeen long enough since last interaction with this app.
                            notifyController = true;
                        }
                        excessive = true;
                    }
                    if (decoupleThresholds && brPercentage >= brThreshold) {
                        if (ts == null) {
@@ -1812,11 +1860,15 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                    final long[] ts = pair.first;
                    final long lastRestrictBucketTs = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET];
                    if (rbPercentage >= rbThreshold) {
                        if (now > lastInteractionTime + mBgCurrentDrainInteractionGracePeriodMs) {
                            if (lastRestrictBucketTs == 0) {
                                ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = now;
                                pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
                            }
                        notifyController = excessive = true;
                            // It's been long enough since last interaction with this app.
                            notifyController = true;
                        }
                        excessive = true;
                    } else {
                        // It's actually back to normal, but we don't untrack it until
                        // explicit user interactions, because the restriction could be the cause
@@ -1833,7 +1885,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                                && (now > lastRestrictBucketTs + mBgCurrentDrainWindowMs));
                        if (notifyController) {
                            ts[TIME_STAMP_INDEX_BG_RESTRICTED] = now;
                            pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = usage;
                            pair.second[TIME_STAMP_INDEX_BG_RESTRICTED] = usage;
                        }
                        excessive = true;
                    } else {
@@ -1841,7 +1893,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                        // user consent to unrestrict it; or if it's in restricted bucket level,
                        // resetting this won't lift it from that level.
                        ts[TIME_STAMP_INDEX_BG_RESTRICTED] = 0;
                        pair.second[TIME_STAMP_INDEX_RESTRICTED_BUCKET] = null;
                        pair.second[TIME_STAMP_INDEX_BG_RESTRICTED] = null;
                        // Now need to notify the controller.
                    }
                }
@@ -1902,6 +1954,7 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
        void onUserInteractionStarted(String packageName, int uid) {
            boolean changed = false;
            synchronized (mLock) {
                mLastInteractionTime.put(uid, SystemClock.elapsedRealtime());
                final int curLevel = mTracker.mAppRestrictionController.getRestrictionLevel(
                        uid, packageName);
                if (curLevel == RESTRICTION_LEVEL_BACKGROUND_RESTRICTED) {
@@ -1940,9 +1993,30 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
        @VisibleForTesting
        void reset() {
            mHighBgBatteryPackages.clear();
            mLastInteractionTime.clear();
            mTracker.reset();
        }

        @GuardedBy("mLock")
        void onUserRemovedLocked(final @UserIdInt int userId) {
            for (int i = mHighBgBatteryPackages.size() - 1; i >= 0; i--) {
                if (UserHandle.getUserId(mHighBgBatteryPackages.keyAt(i)) == userId) {
                    mHighBgBatteryPackages.removeAt(i);
                }
            }
            for (int i = mLastInteractionTime.size() - 1; i >= 0; i--) {
                if (UserHandle.getUserId(mLastInteractionTime.keyAt(i)) == userId) {
                    mLastInteractionTime.removeAt(i);
                }
            }
        }

        @GuardedBy("mLock")
        void onUidRemovedLocked(final int uid) {
            mHighBgBatteryPackages.remove(uid);
            mLastInteractionTime.delete(uid);
        }

        @Override
        void dump(PrintWriter pw, String prefix) {
            pw.print(prefix);
@@ -1976,6 +2050,10 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                pw.print('=');
                pw.println(mBgCurrentDrainWindowMs);
                pw.print(prefix);
                pw.print(KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD);
                pw.print('=');
                pw.println(mBgCurrentDrainInteractionGracePeriodMs);
                pw.print(prefix);
                pw.print(KEY_BG_CURRENT_DRAIN_MEDIA_PLAYBACK_MIN_DURATION);
                pw.print('=');
                pw.println(mBgCurrentDrainMediaPlaybackMinDuration);
+46 −0
Original line number Diff line number Diff line
@@ -582,6 +582,7 @@ public final class BackgroundRestrictionTest {

        DeviceConfigSession<Boolean> bgCurrentDrainMonitor = null;
        DeviceConfigSession<Long> bgCurrentDrainWindow = null;
        DeviceConfigSession<Long> bgCurrentDrainInteractionGracePeriod = null;
        DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null;
        DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null;
        DeviceConfigSession<Boolean> bgPromptFgsWithNotiToBgRestricted = null;
@@ -617,6 +618,14 @@ public final class BackgroundRestrictionTest {
                            R.integer.config_bg_current_drain_window));
            bgCurrentDrainWindow.set(windowMs);

            bgCurrentDrainInteractionGracePeriod = new DeviceConfigSession<>(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD,
                    DeviceConfig::getLong,
                    (long) mContext.getResources().getInteger(
                            R.integer.config_bg_current_drain_window));
            bgCurrentDrainInteractionGracePeriod.set(windowMs);

            bgCurrentDrainRestrictedBucketThreshold = new DeviceConfigSession<>(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET,
@@ -768,6 +777,32 @@ public final class BackgroundRestrictionTest {

            clearInvocations(mInjector.getAppStandbyInternal());

            // It won't be restricted since user just interacted with it.
            runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
                    zeros, new double[]{0, restrictBucketThresholdMah - 1},
                    zeros, new double[]{restrictBucketThresholdMah + 1, 0},
                    () -> {
                        doReturn(mCurrentTimeMillis).when(stats).getStatsStartTimestamp();
                        doReturn(mCurrentTimeMillis + windowMs)
                                .when(stats).getStatsEndTimestamp();
                        mCurrentTimeMillis += windowMs + 1;
                        try {
                            listener.verify(timeout, testUid, testPkgName,
                                    RESTRICTION_LEVEL_RESTRICTED_BUCKET);
                            fail("There shouldn't be any level change events");
                        } catch (Exception e) {
                            // Expected.
                        }
                        verify(mInjector.getAppStandbyInternal(), never()).restrictApp(
                                eq(testPkgName),
                                eq(testUser),
                                anyInt(), anyInt());
                    });

            // Sleep a while.
            Thread.sleep(windowMs);
            clearInvocations(mInjector.getAppStandbyInternal());
            // Now it should have been restricted.
            runTestBgCurrentDrainMonitorOnce(listener, stats, uids,
                    zeros, new double[]{0, restrictBucketThresholdMah - 1},
                    zeros, new double[]{restrictBucketThresholdMah + 1, 0},
@@ -1061,6 +1096,7 @@ public final class BackgroundRestrictionTest {
        } finally {
            closeIfNotNull(bgCurrentDrainMonitor);
            closeIfNotNull(bgCurrentDrainWindow);
            closeIfNotNull(bgCurrentDrainInteractionGracePeriod);
            closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold);
            closeIfNotNull(bgCurrentDrainBgRestrictedThreshold);
            closeIfNotNull(bgPromptFgsWithNotiToBgRestricted);
@@ -1610,6 +1646,7 @@ public final class BackgroundRestrictionTest {

        DeviceConfigSession<Boolean> bgCurrentDrainMonitor = null;
        DeviceConfigSession<Long> bgCurrentDrainWindow = null;
        DeviceConfigSession<Long> bgCurrentDrainInteractionGracePeriod = null;
        DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketThreshold = null;
        DeviceConfigSession<Float> bgCurrentDrainBgRestrictedThreshold = null;
        DeviceConfigSession<Float> bgCurrentDrainRestrictedBucketHighThreshold = null;
@@ -1655,6 +1692,14 @@ public final class BackgroundRestrictionTest {
                            R.integer.config_bg_current_drain_window));
            bgCurrentDrainWindow.set(windowMs);

            bgCurrentDrainInteractionGracePeriod = new DeviceConfigSession<>(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_INTERACTION_GRACE_PERIOD,
                    DeviceConfig::getLong,
                    (long) mContext.getResources().getInteger(
                            R.integer.config_bg_current_drain_window));
            bgCurrentDrainInteractionGracePeriod.set(windowMs);

            bgCurrentDrainRestrictedBucketThreshold = new DeviceConfigSession<>(
                    DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                    AppBatteryPolicy.KEY_BG_CURRENT_DRAIN_THRESHOLD_TO_RESTRICTED_BUCKET,
@@ -2176,6 +2221,7 @@ public final class BackgroundRestrictionTest {
        } finally {
            closeIfNotNull(bgCurrentDrainMonitor);
            closeIfNotNull(bgCurrentDrainWindow);
            closeIfNotNull(bgCurrentDrainInteractionGracePeriod);
            closeIfNotNull(bgCurrentDrainRestrictedBucketThreshold);
            closeIfNotNull(bgCurrentDrainBgRestrictedThreshold);
            closeIfNotNull(bgCurrentDrainRestrictedBucketHighThreshold);