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

Commit 105d9776 authored by Evan Charlton's avatar Evan Charlton
Browse files

Track (and use) UserHandle to make connections

When binding to services, use the UserHandle which registered the
PhoneAccount in order to ensure that the correct user receives the
Intent.

Also make sure that TelecomManager does not leak PhoneAccounts across
profiles, unless the caller is a system-privileged app. PhoneAccounts
will not leak across users, even for system-privileged apps.

Bug: 17421902
Bug: 17421044
Change-Id: I673904a7ae038c88688bba62642e93174e55c308
parent 4ec83c02
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.telecom;

import android.content.ComponentName;
import android.content.Context;
import android.os.UserHandle;
import android.util.Pair;

import com.android.internal.util.IndentingPrintWriter;

@@ -28,8 +30,8 @@ import java.util.HashMap;
 */
final class ConnectionServiceRepository
        implements ServiceBinder.Listener<ConnectionServiceWrapper> {
    private final HashMap<ComponentName, ConnectionServiceWrapper> mServiceCache =
            new HashMap<ComponentName, ConnectionServiceWrapper>();
    private final HashMap<Pair<ComponentName, UserHandle>, ConnectionServiceWrapper> mServiceCache =
            new HashMap<>();
    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
    private final Context mContext;

@@ -38,16 +40,18 @@ final class ConnectionServiceRepository
        mContext = context;
    }

    ConnectionServiceWrapper getService(ComponentName componentName) {
        ConnectionServiceWrapper service = mServiceCache.get(componentName);
    ConnectionServiceWrapper getService(ComponentName componentName, UserHandle userHandle) {
        Pair<ComponentName, UserHandle> cacheKey = Pair.create(componentName, userHandle);
        ConnectionServiceWrapper service = mServiceCache.get(cacheKey);
        if (service == null) {
            service = new ConnectionServiceWrapper(
                    componentName,
                    this,
                    mPhoneAccountRegistrar,
                    mContext);
                    mContext,
                    userHandle);
            service.addListener(this);
            mServiceCache.put(componentName, service);
            mServiceCache.put(cacheKey, service);
        }
        return service;
    }
@@ -70,7 +74,8 @@ final class ConnectionServiceRepository
    public void dump(IndentingPrintWriter pw) {
        pw.println("mServiceCache:");
        pw.increaseIndent();
        for (ComponentName componentName : mServiceCache.keySet()) {
        for (Pair<ComponentName, UserHandle> cacheKey : mServiceCache.keySet()) {
            ComponentName componentName = cacheKey.first;
            pw.println(componentName);
        }
        pw.decreaseIndent();
+7 −3
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.RemoteException;
import android.os.UserHandle;
import android.telecom.AudioState;
import android.telecom.Connection;
import android.telecom.ConnectionRequest;
@@ -591,13 +592,15 @@ final class ConnectionServiceWrapper extends ServiceBinder<IConnectionService> {
     * @param connectionServiceRepository Connection service repository.
     * @param phoneAccountRegistrar Phone account registrar
     * @param context The context.
     * @param userHandle The {@link UserHandle} to use when binding.
     */
    ConnectionServiceWrapper(
            ComponentName componentName,
            ConnectionServiceRepository connectionServiceRepository,
            PhoneAccountRegistrar phoneAccountRegistrar,
            Context context) {
        super(ConnectionService.SERVICE_INTERFACE, componentName, context);
            Context context,
            UserHandle userHandle) {
        super(ConnectionService.SERVICE_INTERFACE, componentName, context, userHandle);
        mConnectionServiceRepository = connectionServiceRepository;
        phoneAccountRegistrar.addListener(new PhoneAccountRegistrar.Listener() {
            // TODO -- Upon changes to PhoneAccountRegistrar, need to re-wire connections
@@ -957,7 +960,8 @@ final class ConnectionServiceWrapper extends ServiceBinder<IConnectionService> {
            PhoneAccount account = mPhoneAccountRegistrar.getPhoneAccount(handle);
            if ((account.getCapabilities() & PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION) != 0) {
                ConnectionServiceWrapper service =
                        mConnectionServiceRepository.getService(handle.getComponentName());
                        mConnectionServiceRepository.getService(handle.getComponentName(),
                                handle.getUserHandle());
                if (service != null) {
                    simServices.add(service);
                }
+3 −1
Original line number Diff line number Diff line
@@ -177,9 +177,11 @@ final class CreateConnectionProcessor {

        if (mResponse != null && attempt != null) {
            Log.i(this, "Trying attempt %s", attempt);
            PhoneAccountHandle phoneAccount = attempt.connectionManagerPhoneAccount;
            ConnectionServiceWrapper service =
                    mRepository.getService(
                            attempt.connectionManagerPhoneAccount.getComponentName());
                            phoneAccount.getComponentName(),
                            phoneAccount.getUserHandle());
            if (service == null) {
                Log.i(this, "Found no connection service for attempt %s", attempt);
                attemptNextPhoneAccount();
+234 −56

File changed.

Preview size limit exceeded, changes collapsed.

+18 −2
Original line number Diff line number Diff line
@@ -22,6 +22,8 @@ import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.os.IInterface;
import android.os.Process;
import android.os.UserHandle;
import android.text.TextUtils;
import android.util.ArraySet;

@@ -82,7 +84,15 @@ abstract class ServiceBinder<ServiceInterface extends IInterface> {
                ServiceConnection connection = new ServiceBinderConnection();

                Log.d(ServiceBinder.this, "Binding to service with intent: %s", serviceIntent);
                if (!mContext.bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE)) {
                final boolean binding;
                if (mUserHandle != null) {
                    binding = mContext.bindServiceAsUser(serviceIntent, connection,
                        Context.BIND_AUTO_CREATE, mUserHandle);
                } else {
                    binding = mContext.bindService(serviceIntent, connection,
                        Context.BIND_AUTO_CREATE);
                }
                if (!binding) {
                    handleFailedConnection();
                    return;
                }
@@ -140,6 +150,9 @@ abstract class ServiceBinder<ServiceInterface extends IInterface> {
    /** Used to bind and unbind from the service. */
    private ServiceConnection mServiceConnection;

    /** {@link UserHandle} to use for binding, to support work profiles and multi-user. */
    private UserHandle mUserHandle;

    /** The binder provided by {@link ServiceConnection#onServiceConnected} */
    private IBinder mBinder;

@@ -166,14 +179,17 @@ abstract class ServiceBinder<ServiceInterface extends IInterface> {
     * @param serviceAction The intent-action used with {@link Context#bindService}.
     * @param componentName The component name of the service with which to bind.
     * @param context The context.
     * @param userHandle The {@link UserHandle} to use for binding.
     */
    protected ServiceBinder(String serviceAction, ComponentName componentName, Context context) {
    protected ServiceBinder(String serviceAction, ComponentName componentName, Context context,
            UserHandle userHandle) {
        Preconditions.checkState(!TextUtils.isEmpty(serviceAction));
        Preconditions.checkNotNull(componentName);

        mContext = context;
        mServiceAction = serviceAction;
        mComponentName = componentName;
        mUserHandle = userHandle;
    }

    final void incrementAssociatedCallCount() {
Loading