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

Commit c0511c2e authored by Michal Karpinski's avatar Michal Karpinski Committed by Android (Google) Code Review
Browse files

Merge "Allow processes that are bound to by a currently foreground app to...

Merge "Allow processes that are bound to by a currently foreground app to start activities from background"
parents 6764eff3 b7daac28
Loading
Loading
Loading
Loading
+38 −21
Original line number Diff line number Diff line
@@ -1524,8 +1524,9 @@ public final class ActiveServices {
        boolean anyClientActivities = false;
        for (int i=proc.services.size()-1; i>=0 && !anyClientActivities; i--) {
            ServiceRecord sr = proc.services.valueAt(i);
            for (int conni=sr.connections.size()-1; conni>=0 && !anyClientActivities; conni--) {
                ArrayList<ConnectionRecord> clist = sr.connections.valueAt(conni);
            ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = sr.getConnections();
            for (int conni = connections.size() - 1; conni >= 0 && !anyClientActivities; conni--) {
                ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
                for (int cri=clist.size()-1; cri>=0; cri--) {
                    ConnectionRecord cr = clist.get(cri);
                    if (cr.binding.client == null || cr.binding.client == proc) {
@@ -1752,10 +1753,10 @@ public final class ActiveServices {
                    callerApp.uid, callerApp.processName, callingPackage);

            IBinder binder = connection.asBinder();
            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
            ArrayList<ConnectionRecord> clist = s.getConnections().get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
                s.connections.put(binder, clist);
                s.putConnection(binder, clist);
            }
            clist.add(c);
            b.connections.add(c);
@@ -1855,8 +1856,9 @@ public final class ActiveServices {
                    b.binder = service;
                    b.requested = true;
                    b.received = true;
                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                    ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                    for (int conni = connections.size() - 1; conni >= 0; conni--) {
                        ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
                        for (int i=0; i<clist.size(); i++) {
                            ConnectionRecord c = clist.get(i);
                            if (!filter.equals(c.binding.intent.intent)) {
@@ -2722,6 +2724,10 @@ public final class ActiveServices {

        updateServiceClientActivitiesLocked(app, null, true);

        if (newService && created) {
            app.addBoundClientUidsOfNewService(r);
        }

        // If the service is in the started state, and there are no
        // pending arguments, then fake up one so its onStartCommand() will
        // be called.
@@ -2881,8 +2887,9 @@ public final class ActiveServices {

        // Report to all of the connections that the service is no longer
        // available.
        for (int conni=r.connections.size()-1; conni>=0; conni--) {
            ArrayList<ConnectionRecord> c = r.connections.valueAt(conni);
        ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
        for (int conni = connections.size() - 1; conni >= 0; conni--) {
            ArrayList<ConnectionRecord> c = connections.valueAt(conni);
            for (int i=0; i<c.size(); i++) {
                ConnectionRecord cr = c.get(i);
                // There is still a connection to the service that is
@@ -3013,6 +3020,7 @@ public final class ActiveServices {
                r.stats.stopLaunchedLocked();
            }
            r.app.services.remove(r);
            r.app.updateBoundClientUids();
            if (r.whitelistManager) {
                updateWhitelistManagerLocked(r.app);
            }
@@ -3065,11 +3073,11 @@ public final class ActiveServices {
        IBinder binder = c.conn.asBinder();
        AppBindRecord b = c.binding;
        ServiceRecord s = b.service;
        ArrayList<ConnectionRecord> clist = s.connections.get(binder);
        ArrayList<ConnectionRecord> clist = s.getConnections().get(binder);
        if (clist != null) {
            clist.remove(c);
            if (clist.size() == 0) {
                s.connections.remove(binder);
                s.removeConnection(binder);
            }
        }
        b.connections.remove(c);
@@ -3294,6 +3302,7 @@ public final class ActiveServices {
            if (finishing) {
                if (r.app != null && !r.app.isPersistent()) {
                    r.app.services.remove(r);
                    r.app.updateBoundClientUids();
                    if (r.whitelistManager) {
                        updateWhitelistManagerLocked(r.app);
                    }
@@ -3389,6 +3398,7 @@ public final class ActiveServices {
                Slog.i(TAG, "  Force stopping service " + service);
                if (service.app != null && !service.app.isPersistent()) {
                    service.app.services.remove(service);
                    service.app.updateBoundClientUids();
                    if (service.whitelistManager) {
                        updateWhitelistManagerLocked(service.app);
                    }
@@ -3504,8 +3514,9 @@ public final class ActiveServices {
                Iterator<ServiceRecord> it = app.services.iterator();
                while (it.hasNext()) {
                    ServiceRecord r = it.next();
                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
                        ArrayList<ConnectionRecord> cl = r.connections.valueAt(conni);
                    ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                    for (int conni=connections.size()-1; conni>=0; conni--) {
                        ArrayList<ConnectionRecord> cl = connections.valueAt(conni);
                        for (int i=0; i<cl.size(); i++) {
                            ConnectionRecord c = cl.get(i);
                            if (c.binding.client != app) {
@@ -3542,6 +3553,7 @@ public final class ActiveServices {
            }
            if (sr.app != app && sr.app != null && !sr.app.isPersistent()) {
                sr.app.services.remove(sr);
                sr.app.updateBoundClientUids();
            }
            sr.setProcess(null);
            sr.isolatedProc = null;
@@ -3605,6 +3617,7 @@ public final class ActiveServices {
            // so make sure the service is cleaned out of it.
            if (!app.isPersistent()) {
                app.services.removeAt(i);
                app.updateBoundClientUids();
            }

            // Sanity check: if the service listed for the app is not one
@@ -3655,6 +3668,7 @@ public final class ActiveServices {

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

            // Make sure there are no more restarting services for this process.
            for (int i=mRestartingServices.size()-1; i>=0; i--) {
@@ -3701,7 +3715,7 @@ public final class ActiveServices {
        info.foreground = r.isForeground;
        info.activeSince = r.createRealTime;
        info.started = r.startRequested;
        info.clientCount = r.connections.size();
        info.clientCount = r.getConnections().size();
        info.crashCount = r.crashCount;
        info.lastActivityTime = r.lastActivity;
        if (r.isForeground) {
@@ -3717,8 +3731,9 @@ public final class ActiveServices {
            info.flags |= ActivityManager.RunningServiceInfo.FLAG_PERSISTENT_PROCESS;
        }

        for (int conni=r.connections.size()-1; conni>=0; conni--) {
            ArrayList<ConnectionRecord> connl = r.connections.valueAt(conni);
        ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
        for (int conni = connections.size() - 1; conni >= 0; conni--) {
            ArrayList<ConnectionRecord> connl = connections.valueAt(conni);
            for (int i=0; i<connl.size(); i++) {
                ConnectionRecord conn = connl.get(i);
                if (conn.clientLabel != 0) {
@@ -3787,9 +3802,10 @@ public final class ActiveServices {
    public PendingIntent getRunningServiceControlPanelLocked(ComponentName name) {
        int userId = UserHandle.getUserId(Binder.getCallingUid());
        ServiceRecord r = getServiceByNameLocked(name, userId);
        ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
        if (r != null) {
            for (int conni=r.connections.size()-1; conni>=0; conni--) {
                ArrayList<ConnectionRecord> conn = r.connections.valueAt(conni);
            for (int conni = connections.size() - 1; conni >= 0; conni--) {
                ArrayList<ConnectionRecord> conn = connections.valueAt(conni);
                for (int i=0; i<conn.size(); i++) {
                    if (conn.get(i).clientIntent != null) {
                        return conn.get(i).clientIntent;
@@ -4080,11 +4096,12 @@ public final class ActiveServices {
                pw.print(" started=");
                pw.print(r.startRequested);
                pw.print(" connections=");
                pw.println(r.connections.size());
                if (r.connections.size() > 0) {
                ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections = r.getConnections();
                pw.println(connections.size());
                if (connections.size() > 0) {
                    pw.println("    Connections:");
                    for (int conni=0; conni<r.connections.size(); conni++) {
                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
                    for (int conni = 0; conni < connections.size(); conni++) {
                        ArrayList<ConnectionRecord> clist = connections.valueAt(conni);
                        for (int i = 0; i < clist.size(); i++) {
                            ConnectionRecord conn = clist.get(i);
                            pw.print("      ");
+5 −2
Original line number Diff line number Diff line
@@ -53,12 +53,14 @@ import android.app.usage.UsageEvents;
import android.content.Context;
import android.os.Binder;
import android.os.Debug;
import android.os.IBinder;
import android.os.PowerManagerInternal;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -1110,12 +1112,13 @@ public final class OomAdjuster {
                }
            }

            for (int conni = s.connections.size() - 1;
            ArrayMap<IBinder, ArrayList<ConnectionRecord>> serviceConnections = s.getConnections();
            for (int conni = serviceConnections.size() - 1;
                    conni >= 0 && (adj > ProcessList.FOREGROUND_APP_ADJ
                            || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
                            || procState > ActivityManager.PROCESS_STATE_TOP);
                    conni--) {
                ArrayList<ConnectionRecord> clist = s.connections.valueAt(conni);
                ArrayList<ConnectionRecord> clist = serviceConnections.valueAt(conni);
                for (int i = 0;
                        i < clist.size() && (adj > ProcessList.FOREGROUND_APP_ADJ
                                || schedGroup == ProcessList.SCHED_GROUP_BACKGROUND
+49 −0
Original line number Diff line number Diff line
@@ -259,6 +259,8 @@ class ProcessRecord implements WindowProcessListener {
    // A set of tokens that currently contribute to this process being temporarily whitelisted
    // to start activities even if it's not in the foreground
    final ArraySet<Binder> mAllowBackgroundActivityStartsTokens = new ArraySet<>();
    // a set of UIDs of all bound clients
    private ArraySet<Integer> mBoundClientUids = new ArraySet<>();

    String isolatedEntryPoint;  // Class to run on start if this is a special isolated process.
    String[] isolatedEntryPointArgs; // Arguments to pass to isolatedEntryPoint's main().
@@ -1193,6 +1195,53 @@ class ProcessRecord implements WindowProcessListener {
                !mAllowBackgroundActivityStartsTokens.isEmpty());
    }

    void addBoundClientUids(ArraySet<Integer> clientUids) {
        mBoundClientUids.addAll(clientUids);
        mWindowProcessController.setBoundClientUids(mBoundClientUids);
    }

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

    void addBoundClientUidsOfNewService(ServiceRecord sr) {
        if (sr == null) {
            return;
        }
        ArrayMap<IBinder, ArrayList<ConnectionRecord>> conns = sr.getConnections();
        for (int conni = conns.size() - 1; conni >= 0; conni--) {
            ArrayList<ConnectionRecord> c = conns.valueAt(conni);
            for (int i = 0; i < c.size(); i++) {
                mBoundClientUids.add(c.get(i).clientUid);
            }
        }
        mWindowProcessController.setBoundClientUids(mBoundClientUids);
    }

    void clearBoundClientUids() {
        mBoundClientUids.clear();
        mWindowProcessController.setBoundClientUids(mBoundClientUids);
    }

    void setActiveInstrumentation(ActiveInstrumentation instr) {
        mInstr = instr;
        boolean isInstrumenting = instr != null;
+30 −1
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
@@ -88,7 +89,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
    final ArrayMap<Intent.FilterComparison, IntentBindRecord> bindings
            = new ArrayMap<Intent.FilterComparison, IntentBindRecord>();
                            // All active bindings to the service.
    final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
    private final ArrayMap<IBinder, ArrayList<ConnectionRecord>> connections
            = new ArrayMap<IBinder, ArrayList<ConnectionRecord>>();
                            // IBinder -> ConnectionRecord of all bound clients

@@ -542,6 +543,7 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
            }
        } else if (app != null) {
            app.removeAllowBackgroundActivityStartsToken(this);
            app.updateBoundClientUids();
        }
        app = _proc;
        if (pendingConnectionGroup > 0 && _proc != null) {
@@ -563,6 +565,33 @@ final class ServiceRecord extends Binder implements ComponentName.WithComponentN
                }
            }
        }
        if (_proc != null) {
            _proc.updateBoundClientUids();
        }
    }

    ArrayMap<IBinder, ArrayList<ConnectionRecord>> getConnections() {
        return connections;
    }

    void putConnection(IBinder binder, ArrayList<ConnectionRecord> clist) {
        connections.put(binder, clist);
        // if we have a process attached, add bound client uids of this connection to it
        if (app != null) {
            ArraySet<Integer> boundClientUids = new ArraySet<>();
            for (int i = 0; i < clist.size(); i++) {
                boundClientUids.add(clist.get(i).clientUid);
            }
            app.addBoundClientUids(boundClientUids);
        }
    }

    void removeConnection(IBinder binder) {
        connections.remove(binder);
        // if we have a process attached, tell it to update the state of bound clients
        if (app != null) {
            app.updateBoundClientUids();
        }
    }

    void updateHasBindingWhitelistingBgActivityStarts() {
+17 −0
Original line number Diff line number Diff line
@@ -114,6 +114,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.service.voice.IVoiceInteractionSession;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.EventLog;
import android.util.Pools.SynchronizedPool;
import android.util.Slog;
@@ -1001,6 +1002,10 @@ class ActivityStarter {
            if (callerApp.hasActivityInVisibleTask()) {
                return false;
            }
            // don't abort if the caller is bound by a UID that's currently foreground
            if (isBoundByForegroundUid(callerApp)) {
                return false;
            }
        }
        // don't abort if the callingUid has START_ACTIVITIES_FROM_BACKGROUND permission
        if (mService.checkPermission(START_ACTIVITIES_FROM_BACKGROUND, callingPid, callingUid)
@@ -1050,6 +1055,18 @@ class ActivityStarter {
        return true;
    }

    private boolean isBoundByForegroundUid(WindowProcessController callerApp) {
        final ArraySet<Integer> boundClientUids = callerApp.getBoundClientUids();
        for (int i = boundClientUids.size() - 1; i >= 0; --i) {
            final int uid = boundClientUids.valueAt(i);
            if (mService.mWindowManager.mRoot.isAnyNonToastWindowVisibleForUid(uid)
                    || mService.getUidState(uid) == ActivityManager.PROCESS_STATE_TOP) {
                return true;
            }
        }
        return false;
    }

    /**
     * Creates a launch intent for the given auxiliary resolution data.
     */
Loading