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

Commit 00157371 authored by Reema Bajwa's avatar Reema Bajwa Committed by Android (Google) Code Review
Browse files

Merge "Implement logic for reacting to package removal"

parents 9ba77666 7c0a2964
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -1049,6 +1049,15 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem

            @Override
            public void onPackageRemoved(String packageName, int uid) {
                if (mServiceNameResolver != null
                        && mServiceNameResolver.isConfiguredInMultipleMode()) {
                    final int userId = getChangingUserId();
                    synchronized (mLock) {
                        handlePackageRemovedMultiModeLocked(packageName, userId);
                    }
                    return;
                }

                synchronized (mLock) {
                    final int userId = getChangingUserId();
                    final S service = peekServiceForUserLocked(userId);
@@ -1092,6 +1101,15 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
            public void onPackageDataCleared(String packageName, int uid) {
                if (verbose) Slog.v(mTag, "onPackageDataCleared(): " + packageName);
                final int userId = getChangingUserId();

                if (mServiceNameResolver != null
                        && mServiceNameResolver.isConfiguredInMultipleMode()) {
                    synchronized (mLock) {
                        onServicePackageDataClearedMultiModeLocked(packageName, userId);
                    }
                    return;
                }

                synchronized (mLock) {
                    final S service = peekServiceForUserLocked(userId);
                    if (service != null) {
@@ -1212,6 +1230,49 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
        monitor.register(getContext(), null, UserHandle.ALL, true);
    }

    @GuardedBy("mLock")
    @SuppressWarnings("unused")
    protected void onServicePackageDataClearedMultiModeLocked(String packageName, int userId) {
        if (verbose) {
            Slog.v(mTag, "onServicePackageDataClearedMultiModeLocked("
                    + userId + ")");
        }
    }

    @GuardedBy("mLock")
    @SuppressWarnings("unused")
    protected void handlePackageRemovedMultiModeLocked(String packageName, int userId) {
        if (verbose) Slog.v(mTag, "handlePackageRemovedMultiModeLocked(" + userId + ")");
    }

    @GuardedBy("mLock")
    protected void removeServiceFromCache(@NonNull S service, int userId) {
        if (mServicesCacheList.get(userId) != null) {
            mServicesCacheList.get(userId).remove(service);
        }
    }

    @GuardedBy("mLock")
    protected void removeServiceFromMultiModeSettings(String serviceComponentName, int userId) {
        final String serviceSettingsProperty = getServiceSettingsProperty();
        if (serviceSettingsProperty == null || mServiceNameResolver == null
                || !mServiceNameResolver.isConfiguredInMultipleMode()) {
            if (verbose) {
                Slog.v(mTag, "removeServiceFromSettings not implemented "
                        + " for single backend implementation");
            }
            return;
        }
        String[] settingComponentNames = mServiceNameResolver.getServiceNameList(userId);
        List<String> remainingServices = new ArrayList<>();
        for (String settingComponentName : settingComponentNames) {
            if (!settingComponentName.equals(serviceComponentName)) {
                remainingServices.add(settingComponentName);
            }
        }
        mServiceNameResolver.setServiceNameList(remainingServices, userId);
    }

    /**
     * Visitor pattern.
     *
+17 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.text.TextUtils;
import android.util.ArraySet;

import java.io.PrintWriter;
import java.util.List;
import java.util.Set;

/**
@@ -91,6 +92,22 @@ public final class SecureSettingsServiceNameResolver extends ServiceNameBaseReso
                mContext.getContentResolver(), mProperty, userId);
    }

    @Override
    public void setServiceNameList(List<String> componentNames, int userId) {
        if (componentNames == null || componentNames.isEmpty()) {
            Settings.Secure.putStringForUser(
                    mContext.getContentResolver(), mProperty, null, userId);
            return;
        }
        StringBuilder builder = new StringBuilder(componentNames.get(0));
        for (int i = 1; i < componentNames.size(); i++) {
            builder.append(COMPONENT_NAME_SEPARATOR);
            builder.append(componentNames.get(i));
        }
        Settings.Secure.putStringForUser(
                mContext.getContentResolver(), mProperty, builder.toString(), userId);
    }

    private String[] parseColonDelimitedServiceNames(String serviceNames) {
        final Set<String> delimitedServices = new ArraySet<>();
        if (!TextUtils.isEmpty(serviceNames)) {
+7 −1
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.UserIdInt;
import com.android.internal.infra.AbstractRemoteService;

import java.io.PrintWriter;
import java.util.List;

/**
 * A helper class used to resolve the name of the app-provided service a
@@ -30,7 +31,6 @@ import java.io.PrintWriter;
 * @hide
 */
public interface ServiceNameResolver {

    /**
     * Listener for name changes.
     */
@@ -77,6 +77,12 @@ public interface ServiceNameResolver {
        }
    }

    /**
     * Set the given list of services to the secure setting
     */
    default void setServiceNameList(List<String> services, int userId) {
    }

    /**
     * Returns whether the resolver is configured to connect to multiple backend services.
     * The default return type is false.
+31 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static android.content.Context.CREDENTIAL_SERVICE;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
import android.credentials.ClearCredentialStateRequest;
@@ -42,10 +43,12 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.service.credentials.BeginCreateCredentialRequest;
import android.service.credentials.BeginGetCredentialRequest;
import android.service.credentials.CredentialProviderInfo;
import android.text.TextUtils;
import android.util.Log;
import android.util.Slog;

import com.android.internal.annotations.GuardedBy;
import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.SecureSettingsServiceNameResolver;

@@ -122,6 +125,34 @@ public final class CredentialManagerService
        return serviceList;
    }

    @GuardedBy("mLock")
    @SuppressWarnings("GuardedBy") // ErrorProne requires service.mLock which is the same
    // this.mLock
    protected void handlePackageRemovedMultiModeLocked(String packageName, int userId) {
        List<CredentialManagerServiceImpl> services = peekServiceListForUserLocked(userId);
        if (services == null) {
            return;
        }
        CredentialManagerServiceImpl serviceToBeRemoved = null;
        for (CredentialManagerServiceImpl service : services) {
            if (service != null) {
                CredentialProviderInfo credentialProviderInfo =
                        service.getCredentialProviderInfo();
                ComponentName componentName = credentialProviderInfo.getServiceInfo()
                        .getComponentName();
                if (packageName.equals(componentName.getPackageName())) {
                    serviceToBeRemoved = service;
                    removeServiceFromMultiModeSettings(componentName.flattenToString(), userId);
                    break;
                }
            }
        }
        if (serviceToBeRemoved != null) {
            removeServiceFromCache(serviceToBeRemoved, userId);
        }
        // TODO("Iterate over system services and remove if needed")
    }

    private void runForUser(@NonNull final Consumer<CredentialManagerServiceImpl> c) {
        final int userId = UserHandle.getCallingUserId();
        final long origId = Binder.clearCallingIdentity();
+24 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ public final class CredentialManagerServiceImpl extends

    // TODO(b/210531) : Make final when update flow is fixed
    @GuardedBy("mLock")
    private CredentialProviderInfo mInfo;
    @NonNull private CredentialProviderInfo mInfo;

    CredentialManagerServiceImpl(
            @NonNull CredentialManagerService master,
@@ -113,4 +113,27 @@ public final class CredentialManagerServiceImpl extends
        }
        return false;
    }

    @GuardedBy("mLock")
    public CredentialProviderInfo getCredentialProviderInfo() {
        return mInfo;
    }

    /**
     * Callback called when an app has been updated.
     *
     * @param packageName package of the app being updated.
     */
    @GuardedBy("mLock")
    protected void handlePackageUpdateLocked(@NonNull String packageName) {
        if (mInfo != null && mInfo.getServiceInfo() != null
                && mInfo.getServiceInfo().getComponentName()
                .getPackageName().equals(packageName)) {
            try {
                newServiceInfoLocked(mInfo.getServiceInfo().getComponentName());
            } catch (PackageManager.NameNotFoundException e) {
                Log.i(TAG, "Issue while updating serviceInfo: " + e.getMessage());
            }
        }
    }
}