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

Commit 7c0a2964 authored by Reema Bajwa's avatar Reema Bajwa
Browse files

Implement logic for reacting to package removal

Test: Built & deployed locally

Change-Id: I87a70cde3b2d306e5312f8747e3e7622a3de033d
parent 9d279390
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -1026,6 +1026,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);
@@ -1069,6 +1078,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) {
@@ -1189,6 +1207,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,
@@ -108,4 +108,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());
            }
        }
    }
}