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

Commit d02044c3 authored by Darryl L Johnson's avatar Darryl L Johnson
Browse files

Disable activity process config override for certain display-based services.

Single session IME services expect their config to be overriden with the
display the IME window is currently on while launching an activity on a
different display will trigger the compat logic to override the config
with the recent display.

A11y and voice interaction services can also have their display config
overriden with activity launches.

Test: WindowProcessControllerTests
Test: MockingOomAdjusterTests
Test: ProcessRecordTests
Test: ActivityManagerServiceTest
Test: OomAdjusterTests

Fixes: 153843194

Change-Id: Ibe0dd25d11935d07362dcfe95f338deda6d6e3da
parent a8761169
Loading
Loading
Loading
Loading
+36 −39
Original line number Original line Diff line number Diff line
@@ -119,7 +119,6 @@ import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.List;
import java.util.Set;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Predicate;
@@ -1753,8 +1752,8 @@ public final class ActiveServices {
    private void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
    private void updateServiceForegroundLocked(ProcessRecord proc, boolean oomAdj) {
        boolean anyForeground = false;
        boolean anyForeground = false;
        int fgServiceTypes = 0;
        int fgServiceTypes = 0;
        for (int i = proc.services.size() - 1; i >= 0; i--) {
        for (int i = proc.numberOfRunningServices() - 1; i >= 0; i--) {
            ServiceRecord sr = proc.services.valueAt(i);
            ServiceRecord sr = proc.getRunningServiceAt(i);
            if (sr.isForeground || sr.fgRequired) {
            if (sr.isForeground || sr.fgRequired) {
                anyForeground = true;
                anyForeground = true;
                fgServiceTypes |= sr.foregroundServiceType;
                fgServiceTypes |= sr.foregroundServiceType;
@@ -1765,8 +1764,8 @@ public final class ActiveServices {


    private void updateWhitelistManagerLocked(ProcessRecord proc) {
    private void updateWhitelistManagerLocked(ProcessRecord proc) {
        proc.whitelistManager = false;
        proc.whitelistManager = false;
        for (int i=proc.services.size()-1; i>=0; i--) {
        for (int i = proc.numberOfRunningServices() - 1; i >= 0; i--) {
            ServiceRecord sr = proc.services.valueAt(i);
            ServiceRecord sr = proc.getRunningServiceAt(i);
            if (sr.whitelistManager) {
            if (sr.whitelistManager) {
                proc.whitelistManager = true;
                proc.whitelistManager = true;
                break;
                break;
@@ -1802,8 +1801,8 @@ public final class ActiveServices {
        }
        }


        boolean anyClientActivities = false;
        boolean anyClientActivities = false;
        for (int i=proc.services.size()-1; i>=0 && !anyClientActivities; i--) {
        for (int i = proc.numberOfRunningServices() - 1; i >= 0 && !anyClientActivities; i--) {
            ServiceRecord sr = proc.services.valueAt(i);
            ServiceRecord sr = proc.getRunningServiceAt(i);
            ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = sr.getConnections();
            ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = sr.getConnections();
            for (int conni = connections.size() - 1; conni >= 0 && !anyClientActivities; conni--) {
            for (int conni = connections.size() - 1; conni >= 0 && !anyClientActivities; conni--) {
                ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
                ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
@@ -2995,7 +2994,7 @@ public final class ActiveServices {
        r.setProcess(app);
        r.setProcess(app);
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();


        final boolean newService = app.services.add(r);
        final boolean newService = app.startService(r);
        bumpServiceExecutingLocked(r, execInFg, "create");
        bumpServiceExecutingLocked(r, execInFg, "create");
        mAm.updateLruProcessLocked(app, false, null);
        mAm.updateLruProcessLocked(app, false, null);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
        updateServiceForegroundLocked(r.app, /* oomAdj= */ false);
@@ -3036,7 +3035,7 @@ public final class ActiveServices {


                // Cleanup.
                // Cleanup.
                if (newService) {
                if (newService) {
                    app.services.remove(r);
                    app.stopService(r);
                    r.setProcess(null);
                    r.setProcess(null);
                }
                }


@@ -3362,7 +3361,7 @@ public final class ActiveServices {
            synchronized (r.stats.getBatteryStats()) {
            synchronized (r.stats.getBatteryStats()) {
                r.stats.stopLaunchedLocked();
                r.stats.stopLaunchedLocked();
            }
            }
            r.app.services.remove(r);
            r.app.stopService(r);
            r.app.updateBoundClientUids();
            r.app.updateBoundClientUids();
            if (r.whitelistManager) {
            if (r.whitelistManager) {
                updateWhitelistManagerLocked(r.app);
                updateWhitelistManagerLocked(r.app);
@@ -3652,7 +3651,7 @@ public final class ActiveServices {
            }
            }
            if (finishing) {
            if (finishing) {
                if (r.app != null && !r.app.isPersistent()) {
                if (r.app != null && !r.app.isPersistent()) {
                    r.app.services.remove(r);
                    r.app.stopService(r);
                    r.app.updateBoundClientUids();
                    r.app.updateBoundClientUids();
                    if (r.whitelistManager) {
                    if (r.whitelistManager) {
                        updateWhitelistManagerLocked(r.app);
                        updateWhitelistManagerLocked(r.app);
@@ -3748,7 +3747,7 @@ public final class ActiveServices {
                didSomething = true;
                didSomething = true;
                Slog.i(TAG, "  Force stopping service " + service);
                Slog.i(TAG, "  Force stopping service " + service);
                if (service.app != null && !service.app.isPersistent()) {
                if (service.app != null && !service.app.isPersistent()) {
                    service.app.services.remove(service);
                    service.app.stopService(service);
                    service.app.updateBoundClientUids();
                    service.app.updateBoundClientUids();
                    if (service.whitelistManager) {
                    if (service.whitelistManager) {
                        updateWhitelistManagerLocked(service.app);
                        updateWhitelistManagerLocked(service.app);
@@ -3861,10 +3860,9 @@ public final class ActiveServices {
        if (false) {
        if (false) {
            // XXX we are letting the client link to the service for
            // XXX we are letting the client link to the service for
            // death notifications.
            // death notifications.
            if (app.services.size() > 0) {
            int numberOfRunningServices = app.numberOfRunningServices();
                Iterator<ServiceRecord> it = app.services.iterator();
            for (int sIndex = 0; sIndex < numberOfRunningServices; sIndex++) {
                while (it.hasNext()) {
                ServiceRecord r = app.getRunningServiceAt(sIndex);
                    ServiceRecord r = it.next();
                ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                for (int conni = connections.size() - 1; conni >= 0; conni--) {
                for (int conni = connections.size() - 1; conni >= 0; conni--) {
                    ArrayList<ConnectionRecord> cl = connections.valueAt(conni);
                    ArrayList<ConnectionRecord> cl = connections.valueAt(conni);
@@ -3884,7 +3882,6 @@ public final class ActiveServices {
                }
                }
            }
            }
        }
        }
        }


        // Clean up any connections this application has to other services.
        // Clean up any connections this application has to other services.
        for (int i = app.connections.size() - 1; i >= 0; i--) {
        for (int i = app.connections.size() - 1; i >= 0; i--) {
@@ -3897,13 +3894,13 @@ public final class ActiveServices {
        app.whitelistManager = false;
        app.whitelistManager = false;


        // Clear app state from services.
        // Clear app state from services.
        for (int i = app.services.size() - 1; i >= 0; i--) {
        for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
            ServiceRecord sr = app.services.valueAt(i);
            ServiceRecord sr = app.getRunningServiceAt(i);
            synchronized (sr.stats.getBatteryStats()) {
            synchronized (sr.stats.getBatteryStats()) {
                sr.stats.stopLaunchedLocked();
                sr.stats.stopLaunchedLocked();
            }
            }
            if (sr.app != app && sr.app != null && !sr.app.isPersistent()) {
            if (sr.app != app && sr.app != null && !sr.app.isPersistent()) {
                sr.app.services.remove(sr);
                sr.app.stopService(sr);
                sr.app.updateBoundClientUids();
                sr.app.updateBoundClientUids();
            }
            }
            sr.setProcess(null);
            sr.setProcess(null);
@@ -3962,13 +3959,13 @@ public final class ActiveServices {
        ServiceMap smap = getServiceMapLocked(app.userId);
        ServiceMap smap = getServiceMapLocked(app.userId);


        // Now do remaining service cleanup.
        // Now do remaining service cleanup.
        for (int i=app.services.size()-1; i>=0; i--) {
        for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
            ServiceRecord sr = app.services.valueAt(i);
            ServiceRecord sr = app.getRunningServiceAt(i);


            // Unless the process is persistent, this process record is going away,
            // Unless the process is persistent, this process record is going away,
            // so make sure the service is cleaned out of it.
            // so make sure the service is cleaned out of it.
            if (!app.isPersistent()) {
            if (!app.isPersistent()) {
                app.services.removeAt(i);
                app.stopService(sr);
                app.updateBoundClientUids();
                app.updateBoundClientUids();
            }
            }


@@ -4018,7 +4015,7 @@ public final class ActiveServices {
        }
        }


        if (!allowRestart) {
        if (!allowRestart) {
            app.services.clear();
            app.stopAllServices();
            app.clearBoundClientUids();
            app.clearBoundClientUids();


            // Make sure there are no more restarting services for this process.
            // Make sure there are no more restarting services for this process.
@@ -4920,8 +4917,8 @@ public final class ActiveServices {
            if (pr.uid != uid) {
            if (pr.uid != uid) {
                continue;
                continue;
            }
            }
            for (int j = pr.services.size() - 1; j >= 0; j--) {
            for (int j = pr.numberOfRunningServices() - 1; j >= 0; j--) {
                ServiceRecord r = pr.services.valueAt(j);
                ServiceRecord r = pr.getRunningServiceAt(j);
                if (!r.isForeground) {
                if (!r.isForeground) {
                    continue;
                    continue;
                }
                }
+1 −1
Original line number Original line Diff line number Diff line
@@ -18172,7 +18172,7 @@ public class ActivityManagerService extends IActivityManager.Stub
        for (int i = mProcessList.mRemovedProcesses.size() - 1; i >= 0; i--) {
        for (int i = mProcessList.mRemovedProcesses.size() - 1; i >= 0; i--) {
            final ProcessRecord app = mProcessList.mRemovedProcesses.get(i);
            final ProcessRecord app = mProcessList.mRemovedProcesses.get(i);
            if (!app.hasActivitiesOrRecentTasks()
            if (!app.hasActivitiesOrRecentTasks()
                    && app.curReceivers.isEmpty() && app.services.size() == 0) {
                    && app.curReceivers.isEmpty() && app.numberOfRunningServices() == 0) {
                Slog.i(
                Slog.i(
                    TAG, "Exiting empty application process "
                    TAG, "Exiting empty application process "
                    + app.toShortString() + " ("
                    + app.toShortString() + " ("
+2 −2
Original line number Original line Diff line number Diff line
@@ -702,10 +702,10 @@ class AppErrors {
        }
        }


        // Bump up the crash count of any services currently running in the proc.
        // Bump up the crash count of any services currently running in the proc.
        for (int i = app.services.size() - 1; i >= 0; i--) {
        for (int i = app.numberOfRunningServices() - 1; i >= 0; i--) {
            // Any services running in the application need to be placed
            // Any services running in the application need to be placed
            // back in the pending list.
            // back in the pending list.
            ServiceRecord sr = app.services.valueAt(i);
            ServiceRecord sr = app.getRunningServiceAt(i);
            // If the service was restarted a while ago, then reset crash count, else increment it.
            // If the service was restarted a while ago, then reset crash count, else increment it.
            if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
            if (now > sr.restartTime + ProcessList.MIN_CRASH_INTERVAL) {
                sr.crashCount = 1;
                sr.crashCount = 1;
+4 −3
Original line number Original line Diff line number Diff line
@@ -837,7 +837,8 @@ public final class OomAdjuster {
                        break;
                        break;
                }
                }


                if (app.isolated && app.services.size() <= 0 && app.isolatedEntryPoint == null) {
                if (app.isolated && app.numberOfRunningServices() <= 0
                        && app.isolatedEntryPoint == null) {
                    // If this is an isolated process, there are no services
                    // If this is an isolated process, there are no services
                    // running in it, and it's not a special process with a
                    // running in it, and it's not a special process with a
                    // custom entry point, then the process is no longer
                    // custom entry point, then the process is no longer
@@ -1446,12 +1447,12 @@ public final class OomAdjuster {
        }
        }


        int capabilityFromFGS = 0; // capability from foreground service.
        int capabilityFromFGS = 0; // capability from foreground service.
        for (int is = app.services.size() - 1;
        for (int is = app.numberOfRunningServices() - 1;
                is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                is >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                        || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                        || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                        || procState > PROCESS_STATE_TOP);
                        || procState > PROCESS_STATE_TOP);
                is--) {
                is--) {
            ServiceRecord s = app.services.valueAt(is);
            ServiceRecord s = app.getRunningServiceAt(is);
            if (s.startRequested) {
            if (s.startRequested) {
                app.hasStartedServices = true;
                app.hasStartedServices = true;
                if (procState > PROCESS_STATE_SERVICE) {
                if (procState > PROCESS_STATE_SERVICE) {
+65 −11
Original line number Original line Diff line number Diff line
@@ -261,9 +261,9 @@ class ProcessRecord implements WindowProcessListener {
    // Controller for error dialogs
    // Controller for error dialogs
    private final ErrorDialogController mDialogController = new ErrorDialogController();
    private final ErrorDialogController mDialogController = new ErrorDialogController();
    // Controller for driving the process state on the window manager side.
    // Controller for driving the process state on the window manager side.
    final private WindowProcessController mWindowProcessController;
    private final WindowProcessController mWindowProcessController;
    // all ServiceRecord running in this process
    // all ServiceRecord running in this process
    final ArraySet<ServiceRecord> services = new ArraySet<>();
    private final ArraySet<ServiceRecord> mServices = new ArraySet<>();
    // services that are currently executing code (need to remain foreground).
    // services that are currently executing code (need to remain foreground).
    final ArraySet<ServiceRecord> executingServices = new ArraySet<>();
    final ArraySet<ServiceRecord> executingServices = new ArraySet<>();
    // All ConnectionRecord this process holds
    // All ConnectionRecord this process holds
@@ -577,10 +577,10 @@ class ProcessRecord implements WindowProcessListener {
            pw.println(Arrays.toString(isolatedEntryPointArgs));
            pw.println(Arrays.toString(isolatedEntryPointArgs));
        }
        }
        mWindowProcessController.dump(pw, prefix);
        mWindowProcessController.dump(pw, prefix);
        if (services.size() > 0) {
        if (mServices.size() > 0) {
            pw.print(prefix); pw.println("Services:");
            pw.print(prefix); pw.println("Services:");
            for (int i=0; i<services.size(); i++) {
            for (int i = 0; i < mServices.size(); i++) {
                pw.print(prefix); pw.print("  - "); pw.println(services.valueAt(i));
                pw.print(prefix); pw.print("  - "); pw.println(mServices.valueAt(i));
            }
            }
        }
        }
        if (executingServices.size() > 0) {
        if (executingServices.size() > 0) {
@@ -735,6 +735,60 @@ class ProcessRecord implements WindowProcessListener {
        }
        }
    }
    }


    /**
     * Records a service as running in the process. Note that this method does not actually start
     * the service, but records the service as started for bookkeeping.
     *
     * @return true if the service was added, false otherwise.
     */
    boolean startService(ServiceRecord record) {
        if (record == null) {
            return false;
        }
        boolean added = mServices.add(record);
        if (added && record.serviceInfo != null) {
            mWindowProcessController.onServiceStarted(record.serviceInfo);
        }
        return added;
    }

    /**
     * Records a service as stopped. Note that like {@link #startService(ServiceRecord)} this method
     * does not actually stop the service, but records the service as stopped for bookkeeping.
     *
     * @return true if the service was removed, false otherwise.
     */
    boolean stopService(ServiceRecord record) {
        return mServices.remove(record);
    }

    /**
     * The same as calling {@link #stopService(ServiceRecord)} on all current running services.
     */
    void stopAllServices() {
        mServices.clear();
    }

    /**
     * Returns the number of services added with {@link #startService(ServiceRecord)} and not yet
     * removed by a call to {@link #stopService(ServiceRecord)} or {@link #stopAllServices()}.
     *
     * @see #startService(ServiceRecord)
     * @see #stopService(ServiceRecord)
     */
    int numberOfRunningServices() {
        return mServices.size();
    }

    /**
     * Returns the service at the specified {@code index}.
     *
     * @see #numberOfRunningServices()
     */
    ServiceRecord getRunningServiceAt(int index) {
        return mServices.valueAt(index);
    }

    void setCached(boolean cached) {
    void setCached(boolean cached) {
        if (mCached != cached) {
        if (mCached != cached) {
            mCached = cached;
            mCached = cached;
@@ -768,9 +822,9 @@ class ProcessRecord implements WindowProcessListener {
            return true;
            return true;
        }
        }


        final int servicesSize = services.size();
        final int servicesSize = mServices.size();
        for (int i = 0; i < servicesSize; i++) {
        for (int i = 0; i < servicesSize; i++) {
            ServiceRecord r = services.valueAt(i);
            ServiceRecord r = mServices.valueAt(i);
            if (r.isForeground) {
            if (r.isForeground) {
                return true;
                return true;
            }
            }
@@ -1289,16 +1343,16 @@ class ProcessRecord implements WindowProcessListener {
    }
    }


    void updateBoundClientUids() {
    void updateBoundClientUids() {
        if (services.isEmpty()) {
        if (mServices.isEmpty()) {
            clearBoundClientUids();
            clearBoundClientUids();
            return;
            return;
        }
        }
        // grab a set of clientUids of all connections of all services
        // grab a set of clientUids of all connections of all services
        ArraySet<Integer> boundClientUids = new ArraySet<>();
        ArraySet<Integer> boundClientUids = new ArraySet<>();
        final int K = services.size();
        final int serviceCount = mServices.size();
        for (int j = 0; j < K; j++) {
        for (int j = 0; j < serviceCount; j++) {
            ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns =
            ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns =
                    services.valueAt(j).getConnections();
                    mServices.valueAt(j).getConnections();
            final int N = conns.size();
            final int N = conns.size();
            for (int conni = 0; conni < N; conni++) {
            for (int conni = 0; conni < N; conni++) {
                ArrayList<ConnectionRecord> c = conns.valueAt(conni);
                ArrayList<ConnectionRecord> c = conns.valueAt(conni);
Loading