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

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

Merge "Don't prompt on bg abuse if the app has a FGS with notification"

parents 7dd11099 8ddcda8b
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -779,6 +779,16 @@ public abstract class ActivityManagerInternal {
         * @param started {@code true} if the process transits from non-FGS state to FGS state.
         */
        void onForegroundServiceStateChanged(String packageName, int uid, int pid, boolean started);

        /**
         * Call when the notification of the foreground service is updated.
         *
         * @param packageName The package name of the process.
         * @param uid The UID of the process.
         * @param foregroundId The current foreground service notification ID, a negative value
         *                     means this notification is being removed.
         */
        void onForegroundServiceNotificationUpdated(String packageName, int uid, int foregroundId);
    }

    /**
+6 −0
Original line number Diff line number Diff line
@@ -5772,4 +5772,10 @@
         current drain threshold.
    -->
    <integer name="config_bg_current_drain_location_min_duration">1800</integer>

    <!-- The behavior for an app with a FGS and its notification is still showing, when the system
         detects it's abusive and should be put into bg restricted level. True - we'll
         show the prompt to user, False - we'll not show it.
    -->
    <bool name="config_bg_prompt_fgs_with_noti_to_bg_restricted">false</bool>
</resources>
+1 −0
Original line number Diff line number Diff line
@@ -4747,4 +4747,5 @@
  <java-symbol type="array" name="config_bg_current_drain_high_threshold_to_bg_restricted" />
  <java-symbol type="integer" name="config_bg_current_drain_media_playback_min_duration" />
  <java-symbol type="integer" name="config_bg_current_drain_location_min_duration" />
  <java-symbol type="bool" name="config_bg_prompt_fgs_with_noti_to_bg_restricted" />
</resources>
+10 −8
Original line number Diff line number Diff line
@@ -1454,13 +1454,16 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                        notifyController = true;
                    } else {
                        excessive = true;
                        if (brPercentage >= mBgCurrentDrainBgRestrictedThreshold[thresholdIndex]) {
                        if (brPercentage >= mBgCurrentDrainBgRestrictedThreshold[thresholdIndex]
                                && curLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET) {
                            // If we're in the restricted standby bucket but still seeing high
                            // current drains, tell the controller again.
                            if (curLevel == RESTRICTION_LEVEL_RESTRICTED_BUCKET
                                    && ts[TIME_STAMP_INDEX_BG_RESTRICTED] == 0) {
                                if (now > ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET]
                                        + mBgCurrentDrainWindowMs) {
                            final long lastResbucket = ts[TIME_STAMP_INDEX_RESTRICTED_BUCKET];
                            final long lastBgRes = ts[TIME_STAMP_INDEX_BG_RESTRICTED];
                            // If it has been a while since restricting the app and since the last
                            // time we notify the controller, notify it again.
                            if ((now >= lastResbucket + mBgCurrentDrainWindowMs) && (lastBgRes == 0
                                    || (now >= lastBgRes + mBgCurrentDrainWindowMs))) {
                                ts[TIME_STAMP_INDEX_BG_RESTRICTED] = now;
                                notifyController = true;
                            }
@@ -1468,7 +1471,6 @@ final class AppBatteryTracker extends BaseAppStateTracker<AppBatteryPolicy>
                    }
                }
            }
            }

            if (excessive) {
                if (DEBUG_BACKGROUND_BATTERY_TRACKER) {
+107 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -52,6 +53,7 @@ import com.android.server.am.AppFGSTracker.PackageDurations;
import com.android.server.am.BaseAppStateEventsTracker.BaseAppStateEventsPolicy;
import com.android.server.am.BaseAppStateTimeEvents.BaseTimeEvent;
import com.android.server.am.BaseAppStateTracker.Injector;
import com.android.server.notification.NotificationManagerInternal;

import java.io.PrintWriter;
import java.lang.reflect.Constructor;
@@ -69,6 +71,9 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac

    private final MyHandler mHandler;

    @GuardedBy("mLock")
    private final UidProcessMap<ArraySet<Integer>> mFGSNotificationIDs = new UidProcessMap<>();

    // Unlocked since it's only accessed in single thread.
    private final ArrayMap<PackageDurations, Long> mTmpPkgDurations = new ArrayMap<>();

@@ -98,11 +103,19 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac
                : MyHandler.MSG_FOREGROUND_SERVICES_STOPPED, pid, uid, packageName).sendToTarget();
    }

    @Override
    public void onForegroundServiceNotificationUpdated(String packageName, int uid,
            int foregroundId) {
        mHandler.obtainMessage(MyHandler.MSG_FOREGROUND_SERVICES_NOTIFICATION_UPDATED,
                uid, foregroundId, packageName).sendToTarget();
    }

    private static class MyHandler extends Handler {
        static final int MSG_FOREGROUND_SERVICES_STARTED = 0;
        static final int MSG_FOREGROUND_SERVICES_STOPPED = 1;
        static final int MSG_FOREGROUND_SERVICES_CHANGED = 2;
        static final int MSG_CHECK_LONG_RUNNING_FGS = 3;
        static final int MSG_FOREGROUND_SERVICES_NOTIFICATION_UPDATED = 3;
        static final int MSG_CHECK_LONG_RUNNING_FGS = 4;

        private final AppFGSTracker mTracker;

@@ -126,6 +139,10 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac
                    mTracker.handleForegroundServicesChanged(
                            (String) msg.obj, msg.arg1, msg.arg2);
                    break;
                case MSG_FOREGROUND_SERVICES_NOTIFICATION_UPDATED:
                    mTracker.handleForegroundServiceNotificationUpdated(
                            (String) msg.obj, msg.arg1, msg.arg2);
                    break;
                case MSG_CHECK_LONG_RUNNING_FGS:
                    mTracker.checkLongRunningFgs();
                    break;
@@ -203,6 +220,44 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac
        }
    }

    private void handleForegroundServiceNotificationUpdated(String packageName, int uid,
            int notificationId) {
        synchronized (mLock) {
            if (notificationId > 0) {
                ArraySet<Integer> notificationIDs = mFGSNotificationIDs.get(uid, packageName);
                if (notificationIDs == null) {
                    notificationIDs = new ArraySet<>();
                    mFGSNotificationIDs.put(uid, packageName, notificationIDs);
                }
                notificationIDs.add(notificationId);
            } else if (notificationId < 0) {
                final ArraySet<Integer> notificationIDs = mFGSNotificationIDs.get(uid, packageName);
                if (notificationIDs != null) {
                    notificationIDs.remove(-notificationId);
                    if (notificationIDs.isEmpty()) {
                        mFGSNotificationIDs.remove(uid, packageName);
                    }
                }
            }
        }
    }

    @GuardedBy("mLock")
    private boolean hasForegroundServiceNotificationsLocked(String packageName, int uid) {
        final ArraySet<Integer> notificationIDs = mFGSNotificationIDs.get(uid, packageName);
        if (notificationIDs == null || notificationIDs.isEmpty()) {
            return false;
        }
        final NotificationManagerInternal nm = mInjector.getNotificationManagerInternal();
        final int userId = UserHandle.getUserId(uid);
        for (int i = notificationIDs.size() - 1; i >= 0; i--) {
            if (nm.isNotificationShown(packageName, null, notificationIDs.valueAt(i), userId)) {
                return true;
            }
        }
        return false;
    }

    @GuardedBy("mLock")
    private void scheduleDurationCheckLocked(long now) {
        // Look for the active FGS with longest running time till now.
@@ -373,6 +428,28 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac
        }
    }

    boolean hasForegroundServiceNotifications(String packageName, int uid) {
        synchronized (mLock) {
            return hasForegroundServiceNotificationsLocked(packageName, uid);
        }
    }

    boolean hasForegroundServiceNotifications(int uid) {
        synchronized (mLock) {
            final SparseArray<ArrayMap<String, ArraySet<Integer>>> map =
                    mFGSNotificationIDs.getMap();
            final ArrayMap<String, ArraySet<Integer>> pkgs = map.get(uid);
            if (pkgs != null) {
                for (int i = pkgs.size() - 1; i >= 0; i--) {
                    if (hasForegroundServiceNotificationsLocked(pkgs.keyAt(i), uid)) {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    @Override
    void dump(PrintWriter pw, String prefix) {
        pw.print(prefix);
@@ -380,6 +457,35 @@ final class AppFGSTracker extends BaseAppStateDurationsTracker<AppFGSPolicy, Pac
        super.dump(pw, "  " + prefix);
    }

    @Override
    void dumpOthers(PrintWriter pw, String prefix) {
        pw.print(prefix);
        pw.println("APPS WITH ACTIVE FOREGROUND SERVICES:");
        prefix = "  " + prefix;
        synchronized (mLock) {
            final SparseArray<ArrayMap<String, ArraySet<Integer>>> map =
                    mFGSNotificationIDs.getMap();
            if (map.size() == 0) {
                pw.print(prefix);
                pw.println("(none)");
            }
            for (int i = 0, size = map.size(); i < size; i++) {
                final int uid = map.keyAt(i);
                final String uidString = UserHandle.formatUid(uid);
                final ArrayMap<String, ArraySet<Integer>> pkgs = map.valueAt(i);
                for (int j = 0, numOfPkgs = pkgs.size(); j < numOfPkgs; j++) {
                    final String pkgName = pkgs.keyAt(j);
                    pw.print(prefix);
                    pw.print(pkgName);
                    pw.print('/');
                    pw.print(uidString);
                    pw.print(" notification=");
                    pw.println(hasForegroundServiceNotificationsLocked(pkgName, uid));
                }
            }
        }
    }

    /**
     * Tracks the durations with active FGS for a given package.
     */
Loading