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

Commit 53dacd6f authored by Reema Bajwa's avatar Reema Bajwa
Browse files

Propagate ancellation signal to cred man service

If developer cancels the get/create request, we propagate
to the remote cancellation signal and clear the session.
This change includes manually checking before sending back a
response to the develoeper, before invoking the UI and before processing
the repsonse of UI, and then propagating the cancellation signal to the
providers.

Could follow up with adding a listener that proactively cancels the
session in addition to the hook points checked manually.

Test: Built & deployed locally
Bug: 264944428

Change-Id: Ia4c0c4d0e758433400d4f086b482fdb273120968
parent ceaf4865
Loading
Loading
Loading
Loading
+17 −4
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.credentials.ClearCredentialStateRequest;
import android.credentials.IClearCredentialStateCallback;
import android.credentials.ui.ProviderData;
import android.credentials.ui.RequestInfo;
import android.os.CancellationSignal;
import android.os.RemoteException;
import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfo;
@@ -41,9 +42,9 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta

    public ClearRequestSession(Context context, int userId, int callingUid,
            IClearCredentialStateCallback callback, ClearCredentialStateRequest request,
            CallingAppInfo callingAppInfo) {
            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
        super(context, userId, callingUid, request, callback, RequestInfo.TYPE_UNDEFINED,
                callingAppInfo);
                callingAppInfo, cancellationSignal);
    }

    /**
@@ -111,6 +112,12 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta

    private void respondToClientWithResponseAndFinish() {
        Log.i(TAG, "respondToClientWithResponseAndFinish");
        if (isSessionCancelled()) {
            // TODO: Differentiate btw cancelled and false
            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
            finishSession(/*propagateCancellation=*/true);
            return;
        }
        try {
            mClientCallback.onSuccess();
            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
@@ -118,18 +125,24 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta
            Log.i(TAG, "Issue while propagating the response to the client");
            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
        }
        finishSession();
        finishSession(/*propagateCancellation=*/false);
    }

    private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
        Log.i(TAG, "respondToClientWithErrorAndFinish");
        if (isSessionCancelled()) {
            // TODO: Differentiate btw cancelled and false
            logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ true);
            finishSession(/*propagateCancellation=*/true);
            return;
        }
        try {
            mClientCallback.onError(errorType, errorMsg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        logApiCalled(RequestType.CLEAR_CREDENTIALS, /* isSuccessful */ false);
        finishSession();
        finishSession(/*propagateCancellation=*/false);
    }

    private void processResponses() {
+18 −4
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.credentials.CredentialManager;
import android.credentials.ICreateCredentialCallback;
import android.credentials.ui.ProviderData;
import android.credentials.ui.RequestInfo;
import android.os.CancellationSignal;
import android.os.RemoteException;
import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfo;
@@ -47,9 +48,10 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
    CreateRequestSession(@NonNull Context context, int userId, int callingUid,
            CreateCredentialRequest request,
            ICreateCredentialCallback callback,
            CallingAppInfo callingAppInfo) {
            CallingAppInfo callingAppInfo,
            CancellationSignal cancellationSignal) {
        super(context, userId, callingUid, request, callback, RequestInfo.TYPE_CREATE,
                callingAppInfo);
                callingAppInfo, cancellationSignal);
    }

    /**
@@ -119,6 +121,12 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR

    private void respondToClientWithResponseAndFinish(CreateCredentialResponse response) {
        Log.i(TAG, "respondToClientWithResponseAndFinish");
        if (isSessionCancelled()) {
            // TODO: Differentiate btw cancelled and false
            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
            finishSession(/*propagateCancellation=*/true);
            return;
        }
        try {
            mClientCallback.onResponse(response);
            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
@@ -126,18 +134,24 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
            Log.i(TAG, "Issue while responding to client: " + e.getMessage());
            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
        }
        finishSession();
        finishSession(/*propagateCancellation=*/false);
    }

    private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
        Log.i(TAG, "respondToClientWithErrorAndFinish");
        if (isSessionCancelled()) {
            // TODO: Differentiate btw cancelled and false
            logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ true);
            finishSession(/*propagateCancellation=*/true);
            return;
        }
        try {
            mClientCallback.onError(errorType, errorMsg);
        } catch (RemoteException e) {
            Log.i(TAG, "Issue while responding to client: " + e.getMessage());
        }
        logApiCalled(RequestType.CREATE_CREDENTIALS, /* isSuccessful */ false);
        finishSession();
        finishSession(/*propagateCancellation=*/false);
    }

    @Override
+8 −10
Original line number Diff line number Diff line
@@ -196,7 +196,6 @@ public final class CredentialManagerService
    }



    @GuardedBy("mLock")
    private List<CredentialManagerServiceImpl> getOrConstructSystemServiceListLock(
            int resolvedUserId) {
@@ -338,7 +337,8 @@ public final class CredentialManagerService
                            callingUid,
                            callback,
                            request,
                            constructCallingAppInfo(callingPackage, userId));
                            constructCallingAppInfo(callingPackage, userId),
                            CancellationSignal.fromTransport(cancelTransport));

            // Initiate all provider sessions
            List<ProviderSession> providerSessions =
@@ -360,8 +360,6 @@ public final class CredentialManagerService
                                    + e.getMessage());
                }
            }

            // Iterate over all provider sessions and invoke the request
            providerSessions.forEach(ProviderSession::invokeSession);
            return cancelTransport;
        }
@@ -385,7 +383,8 @@ public final class CredentialManagerService
                            callingUid,
                            request,
                            callback,
                            constructCallingAppInfo(callingPackage, userId));
                            constructCallingAppInfo(callingPackage, userId),
                            CancellationSignal.fromTransport(cancelTransport));

            // Initiate all provider sessions
            List<ProviderSession> providerSessions =
@@ -405,8 +404,7 @@ public final class CredentialManagerService
            }

            // Iterate over all provider sessions and invoke the request
            providerSessions.forEach(
                    ProviderSession::invokeSession);
            providerSessions.forEach(ProviderSession::invokeSession);
            return cancelTransport;
        }

@@ -497,7 +495,8 @@ public final class CredentialManagerService
                            callingUid,
                            callback,
                            request,
                            constructCallingAppInfo(callingPackage, userId));
                            constructCallingAppInfo(callingPackage, userId),
                            CancellationSignal.fromTransport(cancelTransport));

            // Initiate all provider sessions
            // TODO: Determine if provider needs to have clear capability in their manifest
@@ -518,8 +517,7 @@ public final class CredentialManagerService
            }

            // Iterate over all provider sessions and invoke the request
            providerSessions.forEach(
                    ProviderSession::invokeSession);
            providerSessions.forEach(ProviderSession::invokeSession);
            return cancelTransport;
        }

+17 −5
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.credentials.GetCredentialResponse;
import android.credentials.IGetCredentialCallback;
import android.credentials.ui.ProviderData;
import android.credentials.ui.RequestInfo;
import android.os.CancellationSignal;
import android.os.RemoteException;
import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfo;
@@ -43,8 +44,9 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest

    public GetRequestSession(Context context, int userId, int callingUid,
            IGetCredentialCallback callback, GetCredentialRequest request,
            CallingAppInfo callingAppInfo) {
        super(context, userId, callingUid, request, callback, RequestInfo.TYPE_GET, callingAppInfo);
            CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
        super(context, userId, callingUid, request, callback, RequestInfo.TYPE_GET,
                callingAppInfo, cancellationSignal);
    }

    /**
@@ -102,6 +104,12 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
    }

    private void respondToClientWithResponseAndFinish(GetCredentialResponse response) {
        if (isSessionCancelled()) {
            // TODO: Differentiate btw cancelled and false
            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
            finishSession(/*propagateCancellation=*/true);
            return;
        }
        try {
            mClientCallback.onResponse(response);
            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ true);
@@ -109,18 +117,22 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
            Log.i(TAG, "Issue while responding to client with a response : " + e.getMessage());
            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
        }
        finishSession();
        finishSession(/*propagateCancellation=*/false);
    }

    private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
        if (isSessionCancelled()) {
            logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
            finishSession(/*propagateCancellation=*/true);
            return;
        }
        try {
            mClientCallback.onError(errorType, errorMsg);
        } catch (RemoteException e) {
            Log.i(TAG, "Issue while responding to client with error : " + e.getMessage());

        }
        logApiCalled(RequestType.GET_CREDENTIALS, /* isSuccessful */ false);
        finishSession();
        finishSession(/*propagateCancellation=*/false);
    }

    @Override
+16 −0
Original line number Diff line number Diff line
@@ -23,8 +23,11 @@ import android.content.Context;
import android.credentials.Credential;
import android.credentials.ui.ProviderData;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.os.ICancellationSignal;
import android.os.RemoteException;
import android.service.credentials.CredentialEntry;
import android.service.credentials.CredentialProviderInfo;
import android.util.Log;
import android.util.Pair;

import java.util.UUID;
@@ -49,6 +52,7 @@ public abstract class ProviderSession<T, R>
    @NonNull protected Status mStatus = Status.NOT_STARTED;
    @NonNull protected final ProviderInternalCallback mCallbacks;
    @Nullable protected Credential mFinalCredentialResponse;
    @Nullable protected ICancellationSignal mProviderCancellationSignal;
    @NonNull protected final T mProviderRequest;
    @Nullable protected R mProviderResponse;
    @NonNull protected Boolean mProviderResponseSet = false;
@@ -151,6 +155,18 @@ public abstract class ProviderSession<T, R>
        return  mFinalCredentialResponse;
    }

    /** Propagates cancellation signal to the remote provider service. */
    public void cancelProviderRemoteSession() {
        try {
            if (mProviderCancellationSignal != null) {
                mProviderCancellationSignal.cancel();
            }
            setStatus(Status.CANCELED);
        } catch (RemoteException e) {
            Log.i(TAG, "Issue while cancelling provider session: " + e.getMessage());
        }
    }

    protected void setStatus(@NonNull Status status) {
        mStatus = status;
    }
Loading