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

Commit f965f403 authored by Dianne Hackborn's avatar Dianne Hackborn
Browse files

Fix issue #38037532: Toasts cause apps to become foreground

ForegroundToken is now ImportanceToken, and doesn't actually
cause an app to become foreground (that is not needed for
toasts anyway).

Also improved output and logging -- new logs for changing
in key uid stats, and when force stopping services after a
uid goes idle.

Test: manual

Change-Id: I44dd391bb8d37857be1359f4b7021dc8d2cd0285
parent 718688f3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -200,7 +200,7 @@ interface IActivityManager {
    void setRequestedOrientation(in IBinder token, int requestedOrientation);
    int getRequestedOrientation(in IBinder token);
    void unbindFinished(in IBinder token, in Intent service, boolean doRebind);
    void setProcessForeground(in IBinder token, int pid, boolean isForeground);
    void setProcessImportant(in IBinder token, int pid, boolean isForeground, String reason);
    void setServiceForeground(in ComponentName className, in IBinder token,
            int id, in Notification notification, int flags);
    boolean moveActivityTaskToBack(in IBinder token, boolean nonRoot);
+11 −0
Original line number Diff line number Diff line
@@ -622,6 +622,17 @@ public final class ActiveServices {
                            != ActivityManager.APP_START_MODE_NORMAL) {
                        if (stopping == null) {
                            stopping = new ArrayList<>();
                            String compName = service.name.flattenToShortString();
                            EventLogTags.writeAmStopIdleService(service.appInfo.uid, compName);
                            StringBuilder sb = new StringBuilder(64);
                            sb.append("Stopping service due to app idle: ");
                            UserHandle.formatUid(sb, service.appInfo.uid);
                            sb.append(" ");
                            TimeUtils.formatDuration(service.createTime
                                    - SystemClock.elapsedRealtime(), sb);
                            sb.append(" ");
                            sb.append(compName);
                            Slog.w(TAG, sb.toString());
                            stopping.add(service);
                        }
                    }
+60 −40
Original line number Diff line number Diff line
@@ -812,15 +812,28 @@ public class ActivityManagerService extends IActivityManager.Stub
    final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
    /**
     * All of the processes that have been forced to be foreground.  The key
     * All of the processes that have been forced to be important.  The key
     * is the pid of the caller who requested it (we hold a death
     * link on it).
     */
    abstract class ForegroundToken implements IBinder.DeathRecipient {
        int pid;
        IBinder token;
    abstract class ImportanceToken implements IBinder.DeathRecipient {
        final int pid;
        final IBinder token;
        final String reason;
        ImportanceToken(int _pid, IBinder _token, String _reason) {
            pid = _pid;
            token = _token;
            reason = _reason;
        }
        @Override
        public String toString() {
            return "ImportanceToken { " + Integer.toHexString(System.identityHashCode(this))
                    + " " + reason + " " + pid + " " + token + " }";
        }
    final SparseArray<ForegroundToken> mForegroundProcesses = new SparseArray<ForegroundToken>();
    }
    final SparseArray<ImportanceToken> mImportantProcesses = new SparseArray<ImportanceToken>();
    /**
     * List of records for processes that someone had tried to start before the
@@ -6499,6 +6512,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                if (DEBUG_UID_OBSERVERS) Slog.i(TAG_UID_OBSERVERS,
                        "No more processes in " + old.uidRecord);
                enqueueUidChangeLocked(old.uidRecord, -1, UidRecord.CHANGE_GONE);
                EventLogTags.writeAmUidStopped(uid);
                mActiveUids.remove(uid);
                noteUidProcessState(uid, ActivityManager.PROCESS_STATE_NONEXISTENT);
            }
@@ -6530,6 +6544,7 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            uidRec.updateHasInternetPermission();
            mActiveUids.put(proc.uid, uidRec);
            EventLogTags.writeAmUidRunning(uidRec.uid);
            noteUidProcessState(uidRec.uid, uidRec.curProcState);
            enqueueUidChangeLocked(uidRec, -1, UidRecord.CHANGE_ACTIVE);
        }
@@ -6717,7 +6732,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        app.makeActive(thread, mProcessStats);
        app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
        app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
        app.forcingToForeground = null;
        app.forcingToImportant = null;
        updateProcessForegroundLocked(app, false, false);
        app.hasShownUi = false;
        app.debugging = false;
@@ -7717,20 +7732,20 @@ public class ActivityManagerService extends IActivityManager.Stub
        }
    }
    void foregroundTokenDied(ForegroundToken token) {
    void importanceTokenDied(ImportanceToken token) {
        synchronized (ActivityManagerService.this) {
            synchronized (mPidsSelfLocked) {
                ForegroundToken cur
                    = mForegroundProcesses.get(token.pid);
                ImportanceToken cur
                    = mImportantProcesses.get(token.pid);
                if (cur != token) {
                    return;
                }
                mForegroundProcesses.remove(token.pid);
                mImportantProcesses.remove(token.pid);
                ProcessRecord pr = mPidsSelfLocked.get(token.pid);
                if (pr == null) {
                    return;
                }
                pr.forcingToForeground = null;
                pr.forcingToImportant = null;
                updateProcessForegroundLocked(pr, false, false);
            }
            updateOomAdjLocked();
@@ -7738,9 +7753,9 @@ public class ActivityManagerService extends IActivityManager.Stub
    }
    @Override
    public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
    public void setProcessImportant(IBinder token, int pid, boolean isForeground, String reason) {
        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                "setProcessForeground()");
                "setProcessImportant()");
        synchronized(this) {
            boolean changed = false;
@@ -7750,28 +7765,26 @@ public class ActivityManagerService extends IActivityManager.Stub
                    Slog.w(TAG, "setProcessForeground called on unknown pid: " + pid);
                    return;
                }
                ForegroundToken oldToken = mForegroundProcesses.get(pid);
                ImportanceToken oldToken = mImportantProcesses.get(pid);
                if (oldToken != null) {
                    oldToken.token.unlinkToDeath(oldToken, 0);
                    mForegroundProcesses.remove(pid);
                    mImportantProcesses.remove(pid);
                    if (pr != null) {
                        pr.forcingToForeground = null;
                        pr.forcingToImportant = null;
                    }
                    changed = true;
                }
                if (isForeground && token != null) {
                    ForegroundToken newToken = new ForegroundToken() {
                    ImportanceToken newToken = new ImportanceToken(pid, token, reason) {
                        @Override
                        public void binderDied() {
                            foregroundTokenDied(this);
                            importanceTokenDied(this);
                        }
                    };
                    newToken.pid = pid;
                    newToken.token = token;
                    try {
                        token.linkToDeath(newToken, 0);
                        mForegroundProcesses.put(pid, newToken);
                        pr.forcingToForeground = token;
                        mImportantProcesses.put(pid, newToken);
                        pr.forcingToImportant = newToken;
                        changed = true;
                    } catch (RemoteException e) {
                        // If the process died while doing this, we will later
@@ -15490,12 +15503,12 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        if (mForegroundProcesses.size() > 0) {
        if (mImportantProcesses.size() > 0) {
            synchronized (mPidsSelfLocked) {
                boolean printed = false;
                for (int i=0; i<mForegroundProcesses.size(); i++) {
                for (int i = 0; i< mImportantProcesses.size(); i++) {
                    ProcessRecord r = mPidsSelfLocked.get(
                            mForegroundProcesses.valueAt(i).pid);
                            mImportantProcesses.valueAt(i).pid);
                    if (dumpPackage != null && (r == null
                            || !r.pkgList.containsKey(dumpPackage))) {
                        continue;
@@ -15507,8 +15520,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                        printed = true;
                        printedAnything = true;
                    }
                    pw.print("    PID #"); pw.print(mForegroundProcesses.keyAt(i));
                            pw.print(": "); pw.println(mForegroundProcesses.valueAt(i));
                    pw.print("    PID #"); pw.print(mImportantProcesses.keyAt(i));
                            pw.print(": "); pw.println(mImportantProcesses.valueAt(i));
                }
            }
        }
@@ -17779,7 +17792,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        app.unlinkDeathRecipient();
        app.makeInactive(mProcessStats);
        app.waitingToKill = null;
        app.forcingToForeground = null;
        app.forcingToImportant = null;
        updateProcessForegroundLocked(app, false, false);
        app.foregroundActivities = false;
        app.hasShownUi = false;
@@ -20774,14 +20787,6 @@ public class ActivityManagerService extends IActivityManager.Stub
                app.cached = false;
                app.adjType = "fg-service";
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            } else if (app.forcingToForeground != null) {
                // The user is aware of this app, so make it visible.
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                procState = ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
                app.cached = false;
                app.adjType = "force-fg";
                app.adjSource = app.forcingToForeground;
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            } else if (app.hasOverlayUi) {
                // The process is display an overlay UI.
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
@@ -20792,6 +20797,21 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
        }
        if (adj > ProcessList.PERCEPTIBLE_APP_ADJ
                || procState > ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND) {
            if (app.forcingToImportant != null) {
                // This is currently used for toasts...  they are not interactive, and
                // we don't want them to cause the app to become fully foreground (and
                // thus out of background check), so we yes the best background level we can.
                adj = ProcessList.PERCEPTIBLE_APP_ADJ;
                procState = ActivityManager.PROCESS_STATE_TRANSIENT_BACKGROUND;
                app.cached = false;
                app.adjType = "force-imp";
                app.adjSource = app.forcingToImportant;
                schedGroup = ProcessList.SCHED_GROUP_DEFAULT;
            }
        }
        if (app == mHeavyWeightProcess) {
            if (adj > ProcessList.HEAVY_WEIGHT_APP_ADJ) {
                // We don't want to kill the current heavy-weight process.
@@ -22032,10 +22052,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                        + mConstants.SERVICE_USAGE_INTERACTION_TIME;
            }
        } else {
            // If the app was being forced to the foreground, by say a Toast, then
            // no need to treat it as an interaction
            isInteraction = app.forcingToForeground == null
                    && app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
            isInteraction = app.curProcState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND;
            app.fgInteractionTime = 0;
        }
        if (isInteraction && (!app.reportedInteraction || (nowElapsed-app.interactionEventTime)
@@ -22573,6 +22590,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                } else {
                    if (uidRec.idle) {
                        uidChange = UidRecord.CHANGE_ACTIVE;
                        EventLogTags.writeAmUidActive(uidRec.uid);
                        uidRec.idle = false;
                    }
                    uidRec.lastBackgroundTime = 0;
@@ -22651,6 +22669,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                        if (UserHandle.getAppId(uidRec.uid) == appId) {
                            if (userId == UserHandle.USER_ALL ||
                                    userId == UserHandle.getUserId(uidRec.uid)) {
                                EventLogTags.writeAmUidIdle(uidRec.uid);
                                uidRec.idle = true;
                                Slog.w(TAG, "Idling uid " + UserHandle.formatUid(uidRec.uid)
                                        + " from package " + packageName + " user " + userId);
@@ -22685,6 +22704,7 @@ public class ActivityManagerService extends IActivityManager.Stub
                final long bgTime = uidRec.lastBackgroundTime;
                if (bgTime > 0 && !uidRec.idle) {
                    if (bgTime <= maxBgTime) {
                        EventLogTags.writeAmUidIdle(uidRec.uid);
                        uidRec.idle = true;
                        doStopUidLocked(uidRec.uid, uidRec);
                    } else {
+11 −0
Original line number Diff line number Diff line
@@ -114,3 +114,14 @@ option java_package com.android.server.am

# UserState has changed
30051 am_user_state_changed (id|1|5),(state|1|5)

# Note when any processes of a uid have started running
30052 am_uid_running (UID|1|5)
# Note when all processes of a uid have stopped.
30053 am_uid_stopped (UID|1|5)
# Note when the state of a uid has become active.
30054 am_uid_active (UID|1|5)
# Note when the state of a uid has become idle (background check enforced).
30055 am_uid_idle (UID|1|5)
# Note when a service is being forcibly stopped because its app went idle.
30056 am_stop_idle_service (UID|1|5),(Component Name|3)
+3 −3
Original line number Diff line number Diff line
@@ -135,7 +135,7 @@ final class ProcessRecord {
    long interactionEventTime;  // The time we sent the last interaction event
    long fgInteractionTime;     // When we became foreground for interaction purposes
    String waitingToKill;       // Process is waiting to be killed when in the bg, and reason
    IBinder forcingToForeground;// Token that is forcing this process to be foreground
    Object forcingToImportant;  // Token that is forcing this process to be important
    int adjSeq;                 // Sequence id for identifying oom_adj assignment cycles
    int lruSeq;                 // Sequence id for identifying LRU update cycles
    CompatibilityInfo compat;   // last used compatibility mode
@@ -302,9 +302,9 @@ final class ProcessRecord {
                    pw.print(" hasAboveClient="); pw.print(hasAboveClient);
                    pw.print(" treatLikeActivity="); pw.println(treatLikeActivity);
        }
        if (foregroundServices || forcingToForeground != null) {
        if (foregroundServices || forcingToImportant != null) {
            pw.print(prefix); pw.print("foregroundServices="); pw.print(foregroundServices);
                    pw.print(" forcingToForeground="); pw.println(forcingToForeground);
                    pw.print(" forcingToImportant="); pw.println(forcingToImportant);
        }
        if (reportedInteraction || fgInteractionTime != 0) {
            pw.print(prefix); pw.print("reportedInteraction=");
Loading