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

Commit 78c258ce authored by Martijn Coenen's avatar Martijn Coenen
Browse files

Support attributing a service binding to a different process.

By default, the process that initiates a service binding is the process
that will be used for attribution and computing the OOM priority of the
process hosting the service. In cases like the SDK sandbox, the system
binds to a service on behalf of another application, and we'd like to
OOM priority to be a function of the priority of that other application.

Since we need some way to lookup the corresponding ProcessRecord, pass
in the process name of the SDK sandbox, and store the corresponding
ProcessRecord in AppBindRecord.

This will allow the OomAdjuster to determine its policy based on the
attributed ProcessRecord in AppBindRecord.

Bug: 253399592
API-Coverage-Bug: 265180182
Test: SdkSandbox TEST_MAPPING
Change-Id: Iab4555975aec52bbc3c42ba339b01c1ffbff36d4
parent d5c4fe4b
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -38,7 +38,8 @@ package com.android.server {
package com.android.server.am {

  public interface ActivityManagerLocal {
    method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, @NonNull String, int) throws android.os.RemoteException;
    method public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull android.os.IBinder, @NonNull String, @NonNull String, int) throws android.os.RemoteException;
    method @Deprecated public boolean bindSdkSandboxService(@NonNull android.content.Intent, @NonNull android.content.ServiceConnection, int, @NonNull String, @NonNull String, int) throws android.os.RemoteException;
    method public boolean canStartForegroundService(int, int, @NonNull String);
    method public void killSdkSandboxClientAppProcess(@NonNull android.os.IBinder);
  }
+7 −2
Original line number Diff line number Diff line
@@ -3181,7 +3181,8 @@ public final class ActiveServices {
    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String instanceName, boolean isSdkSandboxService, int sdkSandboxClientAppUid,
            String sdkSandboxClientAppPackage, String callingPackage, final int userId)
            String sdkSandboxClientAppPackage, IApplicationThread sdkSandboxClientApplicationThread,
            String callingPackage, final int userId)
            throws TransactionTooLargeException {
        if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "bindService: " + service
                + " type=" + resolvedType + " conn=" + connection.asBinder()
@@ -3271,6 +3272,10 @@ public final class ActiveServices {
        final boolean allowInstant = (flags & Context.BIND_ALLOW_INSTANT) != 0;
        final boolean inSharedIsolatedProcess = (flags & Context.BIND_SHARED_ISOLATED_PROCESS) != 0;

        ProcessRecord attributedApp = null;
        if (sdkSandboxClientAppUid > 0) {
            attributedApp = mAm.getRecordForAppLOSP(sdkSandboxClientApplicationThread);
        }
        ServiceLookupResult res = retrieveServiceLocked(service, instanceName,
                isSdkSandboxService, sdkSandboxClientAppUid, sdkSandboxClientAppPackage,
                resolvedType, callingPackage, callingPid, callingUid, userId, true, callerFg,
@@ -3283,7 +3288,7 @@ public final class ActiveServices {
            return -1;
        }
        ServiceRecord s = res.record;
        final AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
        final AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp, attributedApp);
        final ProcessServiceRecord clientPsr = b.client.mServices;
        if (clientPsr.numberOfConnections() >= mAm.mConstants.mMaxServiceConnectionsPerProcess) {
            Slog.w(TAG, "bindService exceeded max service connection number per process, "
+15 −0
Original line number Diff line number Diff line
@@ -76,6 +76,8 @@ public interface ActivityManagerLocal {
     * @param conn Receives information as the service is started and stopped.
     *        This must be a valid ServiceConnection object; it must not be null.
     * @param clientAppUid Uid of the app for which the sdk sandbox process needs to be spawned.
     * @param clientApplicationThread ApplicationThread object of the app for which the sdk sandboox
     *                                is spawned.
     * @param clientAppPackage Package of the app for which the sdk sandbox process needs to
     *        be spawned. This package must belong to the clientAppUid.
     * @param processName Unique identifier for the service instance. Each unique name here will
@@ -90,6 +92,19 @@ public interface ActivityManagerLocal {
     * @see Context#bindService(Intent, ServiceConnection, int)
     */
    @SuppressLint("RethrowRemoteException")
    boolean bindSdkSandboxService(@NonNull Intent service, @NonNull ServiceConnection conn,
            int clientAppUid, @NonNull IBinder clientApplicationThread,
            @NonNull String clientAppPackage, @NonNull String processName,
            @Context.BindServiceFlags int flags)
            throws RemoteException;

    /**
     * @deprecated Please use
     * {@link #bindSdkSandboxService(Intent, ServiceConnection, int, IBinder, String, String, int)}
     *
     * This API can't be deleted yet because it can be used by early AdService module versions.
     */
    @SuppressLint("RethrowRemoteException")
    boolean bindSdkSandboxService(@NonNull Intent service, @NonNull ServiceConnection conn,
            int clientAppUid, @NonNull String clientAppPackage, @NonNull String processName,
            @Context.BindServiceFlags int flags)
+36 −6
Original line number Diff line number Diff line
@@ -13090,13 +13090,15 @@ public class ActivityManagerService extends IActivityManager.Stub
            String resolvedType, IServiceConnection connection, int flags, String instanceName,
            String callingPackage, int userId) throws TransactionTooLargeException {
        return bindServiceInstance(caller, token, service, resolvedType, connection, flags,
                instanceName, false, INVALID_UID, null, callingPackage, userId);
                instanceName, false, INVALID_UID, null, null, callingPackage, userId);
    }
    private int bindServiceInstance(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String instanceName,
            boolean isSdkSandboxService, int sdkSandboxClientAppUid,
            String sdkSandboxClientAppPackage, String callingPackage, int userId)
            String sdkSandboxClientAppPackage,
            IApplicationThread sdkSandboxClientApplicationThread,
            String callingPackage, int userId)
            throws TransactionTooLargeException {
        enforceNotIsolatedCaller("bindService");
        enforceAllowedToStartOrBindServiceIfSdkSandbox(service);
@@ -13135,7 +13137,8 @@ public class ActivityManagerService extends IActivityManager.Stub
            synchronized (this) {
                return mServices.bindServiceLocked(caller, token, service, resolvedType, connection,
                        flags, instanceName, isSdkSandboxService, sdkSandboxClientAppUid,
                        sdkSandboxClientAppPackage, callingPackage, userId);
                        sdkSandboxClientAppPackage, sdkSandboxClientApplicationThread,
                        callingPackage, userId);
            }
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
@@ -16922,7 +16925,8 @@ public class ActivityManagerService extends IActivityManager.Stub
        @Override
        public boolean bindSdkSandboxService(Intent service, ServiceConnection conn,
                int clientAppUid, String clientAppPackage, String processName, int flags)
                int clientAppUid, IBinder clientApplicationThread, String clientAppPackage,
                String processName, int flags)
                throws RemoteException {
            if (service == null) {
                throw new IllegalArgumentException("intent is null");
@@ -16947,14 +16951,40 @@ public class ActivityManagerService extends IActivityManager.Stub
            }
            Handler handler = mContext.getMainThreadHandler();
            IApplicationThread clientApplicationThreadVerified = null;
            if (clientApplicationThread != null) {
                // Make sure this is a valid application process
                synchronized (this) {
                    final ProcessRecord rec = getRecordForAppLOSP(clientApplicationThread);
                    if (rec == null) {
                        // This could happen if the calling process has disappeared; no need for the
                        // sandbox to be even started in this case.
                        Slog.i(TAG, "clientApplicationThread process not found.");
                        return false;
                    }
                    if (rec.info.uid != clientAppUid) {
                        throw new IllegalArgumentException("clientApplicationThread does not match "
                                + " client uid");
                    }
                    clientApplicationThreadVerified = rec.getThread();
                }
            }
            final IServiceConnection sd = mContext.getServiceDispatcher(conn, handler, flags);
            service.prepareToLeaveProcess(mContext);
            return ActivityManagerService.this.bindServiceInstance(
                    mContext.getIApplicationThread(), mContext.getActivityToken(), service,
                    service.resolveTypeIfNeeded(mContext.getContentResolver()), sd, flags,
                    processName, /*isSdkSandboxService*/ true, clientAppUid, clientAppPackage,
                    mContext.getOpPackageName(), UserHandle.getUserId(clientAppUid)) != 0;
                    clientApplicationThreadVerified, mContext.getOpPackageName(),
                    UserHandle.getUserId(clientAppUid)) != 0;
        }
        @Override
        public boolean bindSdkSandboxService(Intent service, ServiceConnection conn,
                int clientAppUid, String clientAppPackage, String processName, int flags)
                throws RemoteException {
            return bindSdkSandboxService(service, conn, clientAppUid,
                    null /* clientApplicationThread */, clientAppPackage, processName, flags);
        }
        @Override
+5 −2
Original line number Diff line number Diff line
@@ -28,13 +28,15 @@ final class AppBindRecord {
    final ServiceRecord service;    // The running service.
    final IntentBindRecord intent;  // The intent we are bound to.
    final ProcessRecord client;     // Who has started/bound the service.

    final ProcessRecord attributedClient; // The binding was done by the system on behalf
                                          // of 'attributedClient'
    final ArraySet<ConnectionRecord> connections = new ArraySet<>();
                                    // All ConnectionRecord for this client.

    void dump(PrintWriter pw, String prefix) {
        pw.println(prefix + "service=" + service);
        pw.println(prefix + "client=" + client);
        pw.println(prefix + "attributedClient=" + attributedClient);
        dumpInIntentBind(pw, prefix);
    }

@@ -50,10 +52,11 @@ final class AppBindRecord {
    }

    AppBindRecord(ServiceRecord _service, IntentBindRecord _intent,
            ProcessRecord _client) {
            ProcessRecord _client, ProcessRecord _attributedClient) {
        service = _service;
        intent = _intent;
        client = _client;
        attributedClient = _attributedClient;
    }

    public String toString() {
Loading