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

Commit 84795f77 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by android-build-merger
Browse files

Merge "Work on issue #36891897: Need to ensure foreground services..." into oc-dev

am: ef055443

Change-Id: I39ad3ffce83c1817bdc8aa7ab9f623d1b683d983
parents c31da7a2 ef055443
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -695,6 +695,14 @@ public class Handler {
        return mQueue.hasMessages(this, what, null);
    }

    /**
     * Return whether there are any messages or callbacks currently scheduled on this handler.
     * @hide
     */
    public final boolean hasMessagesOrCallbacks() {
        return mQueue.hasMessages(this);
    }

    /**
     * Check if there are any pending posts of messages with code 'what' and
     * whose obj is 'object' in the message queue.
@@ -728,6 +736,18 @@ public class Handler {
        }
    }

    /**
     * @hide
     */
    public final void dumpMine(Printer pw, String prefix) {
        pw.println(prefix + this + " @ " + SystemClock.uptimeMillis());
        if (mLooper == null) {
            pw.println(prefix + "looper uninitialized");
        } else {
            mLooper.dump(pw, prefix + "  ", this);
        }
    }

    @Override
    public String toString() {
        return "Handler (" + getClass().getName() + ") {"
+14 −1
Original line number Diff line number Diff line
@@ -310,7 +310,20 @@ public final class Looper {
     */
    public void dump(@NonNull Printer pw, @NonNull String prefix) {
        pw.println(prefix + toString());
        mQueue.dump(pw, prefix + "  ");
        mQueue.dump(pw, prefix + "  ", null);
    }

    /**
     * Dumps the state of the looper for debugging purposes.
     *
     * @param pw A printer to receive the contents of the dump.
     * @param prefix A prefix to prepend to each line which is printed.
     * @param handler Only dump messages for this Handler.
     * @hide
     */
    public void dump(@NonNull Printer pw, @NonNull String prefix, Handler handler) {
        pw.println(prefix + toString());
        mQueue.dump(pw, prefix + "  ", handler);
    }

    /** @hide */
+21 −2
Original line number Diff line number Diff line
@@ -620,6 +620,23 @@ public final class MessageQueue {
        }
    }

    boolean hasMessages(Handler h) {
        if (h == null) {
            return false;
        }

        synchronized (this) {
            Message p = mMessages;
            while (p != null) {
                if (p.target == h) {
                    return true;
                }
                p = p.next;
            }
            return false;
        }
    }

    void removeMessages(Handler h, int what, Object object) {
        if (h == null) {
            return;
@@ -759,12 +776,14 @@ public final class MessageQueue {
        }
    }

    void dump(Printer pw, String prefix) {
    void dump(Printer pw, String prefix, Handler h) {
        synchronized (this) {
            long now = SystemClock.uptimeMillis();
            int n = 0;
            for (Message msg = mMessages; msg != null; msg = msg.next) {
                if (h == null || h == msg.target) {
                    pw.println(prefix + "Message " + n + ": " + msg.toString(now));
                }
                n++;
            }
            pw.println(prefix + "(Total messages: " + n + ", polling=" + isPollingLocked()
+4 −1
Original line number Diff line number Diff line
@@ -9038,7 +9038,10 @@ public final class Settings {
         * <pre>
         * max_cached_processes                 (int)
         * background_settle_time               (long)
         * foreground_service_ui_min_time       (long)
         * fgservice_min_shown_time             (long)
         * fgservice_min_report_time            (long)
         * fgservice_screen_on_before_time      (long)
         * fgservice_screen_on_after_time       (long)
         * content_provider_retain_time         (long)
         * gc_timeout                           (long)
         * gc_min_interval                      (long)
+108 −36
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.util.EventLog;
import android.util.PrintWriterPrinter;
import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
@@ -175,6 +176,9 @@ public final class ActiveServices {
        long mStartVisibleTime;
        long mEndTime;
        int mNumActive;

        // Temp output of foregroundAppShownEnoughLocked
        long mHideTime;
    }

    /**
@@ -736,50 +740,90 @@ public final class ActiveServices {
        }
    }

    boolean foregroundAppShownEnoughLocked(ActiveForegroundApp aa, long nowElapsed) {
        if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Shown enough: pkg=" + aa.mPackageName + ", uid="
                + aa.mUid);
        boolean canRemove = false;
        aa.mHideTime = Long.MAX_VALUE;
        if (aa.mShownWhileTop) {
            // If the app was ever at the top of the screen while the foreground
            // service was running, then we can always just immediately remove it.
            canRemove = true;
            if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - shown while on top");
        } else if (mScreenOn || aa.mShownWhileScreenOn) {
            final long minTime = aa.mStartVisibleTime
                    + (aa.mStartTime != aa.mStartVisibleTime
                            ? mAm.mConstants.FGSERVICE_SCREEN_ON_AFTER_TIME
                            : mAm.mConstants.FGSERVICE_MIN_SHOWN_TIME);
            if (nowElapsed >= minTime) {
                // If shown while the screen is on, and it has been shown for
                // at least the minimum show time, then we can now remove it.
                if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - shown long enough with screen on");
                canRemove = true;
            } else {
                // This is when we will be okay to stop telling the user.
                long reportTime = nowElapsed + mAm.mConstants.FGSERVICE_MIN_REPORT_TIME;
                aa.mHideTime = reportTime > minTime ? reportTime : minTime;
                if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "NO -- wait " + (aa.mHideTime-nowElapsed)
                        + " with screen on");
            }
        } else {
            final long minTime = aa.mEndTime
                    + mAm.mConstants.FGSERVICE_SCREEN_ON_BEFORE_TIME;
            if (nowElapsed >= minTime) {
                // If the foreground service has only run while the screen is
                // off, but it has been gone now for long enough that we won't
                // care to tell the user about it when the screen comes back on,
                // then we can remove it now.
                if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "YES - gone long enough with screen off");
                canRemove = true;
            } else {
                // This is when we won't care about this old fg service.
                aa.mHideTime = minTime;
                if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "NO -- wait " + (aa.mHideTime-nowElapsed)
                        + " with screen off");
            }
        }
        return canRemove;
    }

    void updateForegroundApps(ServiceMap smap) {
        // This is called from the handler without the lock held.
        ArrayList<ActiveForegroundApp> active = null;
        synchronized (mAm) {
            final long now = SystemClock.elapsedRealtime();
            final long nowPlusMin = now + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME;
            long nextUpdateTime = Long.MAX_VALUE;
            if (smap != null) {
                if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Updating foreground apps for user "
                        + smap.mUserId);
                for (int i = smap.mActiveForegroundApps.size()-1; i >= 0; i--) {
                    ActiveForegroundApp aa = smap.mActiveForegroundApps.valueAt(i);
                    if (aa.mEndTime != 0 && (mScreenOn || aa.mShownWhileScreenOn)) {
                        if (!aa.mShownWhileTop && aa.mEndTime < (aa.mStartVisibleTime
                                + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) {
                            // Check to see if this should still be displayed...  we continue
                            // until it has been shown for at least the timeout duration.
                            if (nowPlusMin >= aa.mStartVisibleTime) {
                                // All over!
                                smap.mActiveForegroundApps.removeAt(i);
                                smap.mActiveForegroundAppsChanged = true;
                                continue;
                            } else {
                                long hideTime = aa.mStartVisibleTime
                                        + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME;
                                if (hideTime < nextUpdateTime) {
                                    nextUpdateTime = hideTime;
                                }
                            }
                        } else {
                    if (aa.mEndTime != 0) {
                        boolean canRemove = foregroundAppShownEnoughLocked(aa, now);
                        if (canRemove) {
                            // This was up for longer than the timeout, so just remove immediately.
                            smap.mActiveForegroundApps.removeAt(i);
                            smap.mActiveForegroundAppsChanged = true;
                            continue;
                        }
                        if (aa.mHideTime < nextUpdateTime) {
                            nextUpdateTime = aa.mHideTime;
                        }
                    }
                    if (!aa.mAppOnTop) {
                        if (active == null) {
                            active = new ArrayList<>();
                        }
                        if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Adding active: pkg="
                                + aa.mPackageName + ", uid=" + aa.mUid);
                        active.add(aa);
                    }
                }
                smap.removeMessages(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
                if (nextUpdateTime < Long.MAX_VALUE) {
                    Message msg = smap.obtainMessage();
                    if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Next update time in: "
                            + (nextUpdateTime-now));
                    Message msg = smap.obtainMessage(ServiceMap.MSG_UPDATE_FOREGROUND_APPS);
                    smap.sendMessageAtTime(msg, nextUpdateTime
                            + SystemClock.uptimeMillis() - SystemClock.elapsedRealtime());
                }
@@ -882,15 +926,14 @@ public final class ActiveServices {
            active.mNumActive--;
            if (active.mNumActive <= 0) {
                active.mEndTime = SystemClock.elapsedRealtime();
                if (active.mShownWhileTop || active.mEndTime >= (active.mStartVisibleTime
                        + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME)) {
                if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Ended running of service");
                if (foregroundAppShownEnoughLocked(active, active.mEndTime)) {
                    // Have been active for long enough that we will remove it immediately.
                    smap.mActiveForegroundApps.remove(r.packageName);
                    smap.mActiveForegroundAppsChanged = true;
                    requestUpdateActiveForegroundAppsLocked(smap, 0);
                } else {
                    requestUpdateActiveForegroundAppsLocked(smap, active.mStartVisibleTime
                            + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME);
                } else if (active.mHideTime < Long.MAX_VALUE){
                    requestUpdateActiveForegroundAppsLocked(smap, active.mHideTime);
                }
            }
        }
@@ -904,26 +947,44 @@ public final class ActiveServices {
            // services that were started while the screen was off.
            if (screenOn) {
                final long nowElapsed = SystemClock.elapsedRealtime();
                if (DEBUG_FOREGROUND_SERVICE) Slog.d(TAG, "Screen turned on");
                for (int i = mServiceMap.size()-1; i >= 0; i--) {
                    ServiceMap smap = mServiceMap.valueAt(i);
                    long nextUpdateTime = Long.MAX_VALUE;
                    boolean changed = false;
                    for (int j = smap.mActiveForegroundApps.size()-1; j >= 0; j--) {
                        ActiveForegroundApp active = smap.mActiveForegroundApps.valueAt(j);
                        if (active.mEndTime == 0) {
                            if (!active.mShownWhileScreenOn) {
                            changed = true;
                            active.mShownWhileScreenOn = mScreenOn;
                                active.mShownWhileScreenOn = true;
                                active.mStartVisibleTime = nowElapsed;
                            if (active.mEndTime != 0) {
                                active.mEndTime = nowElapsed;
                            }
                        } else {
                            if (!active.mShownWhileScreenOn
                                    && active.mStartVisibleTime == active.mStartTime) {
                                // If this was never shown while the screen was on, then we will
                                // count the time it started being visible as now, to tell the user
                                // about it now that they have a screen to look at.
                                active.mEndTime = active.mStartVisibleTime = nowElapsed;
                            }
                            if (foregroundAppShownEnoughLocked(active, nowElapsed)) {
                                // Have been active for long enough that we will remove it
                                // immediately.
                                smap.mActiveForegroundApps.remove(active.mPackageName);
                                smap.mActiveForegroundAppsChanged = true;
                                changed = true;
                            } else {
                                if (active.mHideTime < nextUpdateTime) {
                                    nextUpdateTime = active.mHideTime;
                                }
                            }
                        }
                    }
                    if (changed) {
                        requestUpdateActiveForegroundAppsLocked(smap,
                                nowElapsed + mAm.mConstants.FOREGROUND_SERVICE_UI_MIN_TIME);
                    } else if (smap.mActiveForegroundApps.size() > 0) {
                        // Just being paranoid.
                        // Need to immediately update.
                        requestUpdateActiveForegroundAppsLocked(smap, 0);
                    } else if (nextUpdateTime < Long.MAX_VALUE) {
                        requestUpdateActiveForegroundAppsLocked(smap, nextUpdateTime);
                    }
                }
            }
@@ -2318,7 +2379,7 @@ public final class ActiveServices {
            return true;
        }

        // Is someone still bound to us keepign us running?
        // Is someone still bound to us keeping us running?
        if (!knowConn) {
            hasConn = r.hasAutoCreateConnections();
        }
@@ -3741,6 +3802,17 @@ public final class ActiveServices {
                            pw.println();
                        }
                    }
                    if (smap.hasMessagesOrCallbacks()) {
                        if (needSep) {
                            pw.println();
                        }
                        printedAnything = true;
                        needSep = true;
                        pw.print("  Handler - user ");
                        pw.print(user);
                        pw.println(":");
                        smap.dumpMine(new PrintWriterPrinter(pw), "    ");
                    }
                }
            }

Loading