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

Commit 61ae7133 authored by Reema Bajwa's avatar Reema Bajwa
Browse files

Add error propagation piping for get & create

Test: Built & deployed locally

Change-Id: I67b57b228722ffce8a10e9269ef53ffa35fc18fc
parent 71d7b807
Loading
Loading
Loading
Loading
+51 −0
Original line number Original line Diff line number Diff line
@@ -16,18 +16,13 @@


package android.service.credentials;
package android.service.credentials;


import android.annotation.IntDef;
import android.annotation.NonNull;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
/**
 * Contains custom exceptions to be used by credential providers on failure.
 * Contains custom error codes to be used internally for various credential
 * provider error states.
 *
 *
 * @hide
 * @hide
 */
 */
public class CredentialProviderException extends Exception {
public class CredentialProviderErrors {
    public static final int ERROR_UNKNOWN = 0;
    public static final int ERROR_UNKNOWN = 0;


    /**
    /**
@@ -48,49 +43,9 @@ public class CredentialProviderException extends Exception {


    /**
    /**
     * For internal use only.
     * For internal use only.
     * Error code to be used when the provider encounters a failure while processing the request.
     * Error code to be used when an exception is received from the provider.
     *
     *
     * @hide
     * @hide
     */
     */
    public static final int ERROR_PROVIDER_FAILURE = 3;
    public static final int ERROR_PROVIDER_FAILURE = 3;

    private final int mErrorCode;

    /**
     * @hide
     */
    @IntDef(prefix = {"ERROR_"}, value = {
            ERROR_UNKNOWN,
            ERROR_TIMEOUT,
            ERROR_TASK_CANCELED
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface CredentialProviderError { }

    public CredentialProviderException(@CredentialProviderError int errorCode,
            @NonNull String message, @NonNull Throwable cause) {
        super(message, cause);
        mErrorCode = errorCode;
    }

    public CredentialProviderException(@CredentialProviderError int errorCode,
            @NonNull String message) {
        super(message);
        mErrorCode = errorCode;
    }

    public CredentialProviderException(@CredentialProviderError int errorCode,
            @NonNull Throwable cause) {
        super(cause);
        mErrorCode = errorCode;
    }

    public CredentialProviderException(@CredentialProviderError int errorCode) {
        super();
        mErrorCode = errorCode;
    }

    public @CredentialProviderError int getErrorCode() {
        return mErrorCode;
    }
}
}
+39 −12
Original line number Original line Diff line number Diff line
@@ -83,16 +83,6 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
        }
        }
    }
    }


    private void respondToClientAndFinish(CreateCredentialResponse response) {
        Log.i(TAG, "respondToClientAndFinish");
        try {
            mClientCallback.onResponse(response);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        finishSession();
    }

    @Override
    @Override
    public void onProviderStatusChanged(ProviderSession.Status status,
    public void onProviderStatusChanged(ProviderSession.Status status,
            ComponentName componentName) {
            ComponentName componentName) {
@@ -101,10 +91,47 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR


    @Override
    @Override
    public void onFinalResponseReceived(ComponentName componentName,
    public void onFinalResponseReceived(ComponentName componentName,
            CreateCredentialResponse response) {
            @Nullable CreateCredentialResponse response) {
        Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
        Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
        if (response != null) {
        if (response != null) {
            respondToClientAndFinish(response);
            respondToClientWithResponseAndFinish(response);
        } else {
            // TODO("Replace with properly defined error type)
            respondToClientWithErrorAndFinish("unknown_type",
                    "Invalid response");
        }
    }

    @Override
    public void onFinalErrorReceived(ComponentName componentName, String errorType,
            String message) {
        respondToClientWithErrorAndFinish(errorType, message);
    }

    @Override
    public void onUiCancellation() {
        // TODO("Replace with properly defined error type")
        respondToClientWithErrorAndFinish("user_cancelled",
                "User cancelled the selector");
    }
    }

    private void respondToClientWithResponseAndFinish(CreateCredentialResponse response) {
        Log.i(TAG, "respondToClientWithResponseAndFinish");
        try {
            mClientCallback.onResponse(response);
        } catch (RemoteException e) {
            Log.i(TAG, "Issue while responding to client: " + e.getMessage());
        }
        finishSession();
    }

    private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
        Log.i(TAG, "respondToClientWithErrorAndFinish");
        try {
            mClientCallback.onError(errorType, errorMsg);
        } catch (RemoteException e) {
            Log.i(TAG, "Issue while responding to client: " + e.getMessage());
        }
        finishSession();
    }
    }
}
}
+25 −7
Original line number Original line Diff line number Diff line
@@ -175,12 +175,20 @@ public final class CredentialManagerService


            // Initiate all provider sessions
            // Initiate all provider sessions
            List<ProviderSession> providerSessions =
            List<ProviderSession> providerSessions =
                    initiateProviderSessions(
                    initiateProviderSessions(session, request.getGetCredentialOptions()
                            session,
                            .stream().map(GetCredentialOption::getType)
                            request.getGetCredentialOptions().stream()
                                    .map(GetCredentialOption::getType)
                            .collect(Collectors.toList()));
                            .collect(Collectors.toList()));
            // TODO : Return error when no providers available

            if (providerSessions.isEmpty()) {
                try {
                    // TODO("Replace with properly defined error type")
                    callback.onError("unknown_type",
                            "No providers available to fulfill request.");
                } catch (RemoteException e) {
                    Log.i(TAG, "Issue invoking onError on IGetCredentialCallback "
                            + "callback: " + e.getMessage());
                }
            }


            // Iterate over all provider sessions and invoke the request
            // Iterate over all provider sessions and invoke the request
            providerSessions.forEach(providerGetSession -> {
            providerSessions.forEach(providerGetSession -> {
@@ -212,7 +220,17 @@ public final class CredentialManagerService
            // Initiate all provider sessions
            // Initiate all provider sessions
            List<ProviderSession> providerSessions =
            List<ProviderSession> providerSessions =
                    initiateProviderSessions(session, List.of(request.getType()));
                    initiateProviderSessions(session, List.of(request.getType()));
            // TODO : Return error when no providers available

            if (providerSessions.isEmpty()) {
                try {
                    // TODO("Replace with properly defined error type")
                    callback.onError("unknown_type",
                            "No providers available to fulfill request.");
                } catch (RemoteException e) {
                    Log.i(TAG, "Issue invoking onError on ICreateCredentialCallback "
                            + "callback: " + e.getMessage());
                }
            }


            // Iterate over all provider sessions and invoke the request
            // Iterate over all provider sessions and invoke the request
            providerSessions.forEach(
            providerSessions.forEach(
+33 −4
Original line number Original line Diff line number Diff line
@@ -88,15 +88,27 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest


    @Override
    @Override
    public void onFinalResponseReceived(ComponentName componentName,
    public void onFinalResponseReceived(ComponentName componentName,
            GetCredentialResponse response) {
            @Nullable GetCredentialResponse response) {
        Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
        Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
        if (response != null) {
        if (response != null) {
            respondToClientAndFinish(response);
            respondToClientWithResponseAndFinish(response);
        } else {
            // TODO("Replace with no credentials/unknown type when ready)
            respondToClientWithErrorAndFinish("unknown_type",
                    "Invalid response from provider");
        }
        }
    }
    }


    private void respondToClientAndFinish(GetCredentialResponse response) {
    //TODO: Try moving the three error & response methods below to RequestSession to be shared
        Log.i(TAG, "respondToClientAndFinish");
    // between get & create.
    @Override
    public void onFinalErrorReceived(ComponentName componentName, String errorType,
            String message) {
        respondToClientWithErrorAndFinish(errorType, message);
    }

    private void respondToClientWithResponseAndFinish(GetCredentialResponse response) {
        Log.i(TAG, "respondToClientWithResponseAndFinish");
        try {
        try {
            mClientCallback.onResponse(response);
            mClientCallback.onResponse(response);
        } catch (RemoteException e) {
        } catch (RemoteException e) {
@@ -104,4 +116,21 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
        }
        }
        finishSession();
        finishSession();
    }
    }

    private void respondToClientWithErrorAndFinish(String errorType, String errorMsg) {
        Log.i(TAG, "respondToClientWithErrorAndFinish");
        try {
            mClientCallback.onError(errorType, errorMsg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
        finishSession();
    }

    @Override
    public void onUiCancellation() {
        // TODO("Replace with properly defined error type")
        respondToClientWithErrorAndFinish("user_canceled",
                "User cancelled the selector");
    }
}
}
+27 −1
Original line number Original line Diff line number Diff line
@@ -18,7 +18,9 @@ package com.android.server.credentials;


import android.app.Activity;
import android.app.Activity;
import android.content.Intent;
import android.content.Intent;
import android.credentials.CreateCredentialException;
import android.credentials.CreateCredentialResponse;
import android.credentials.CreateCredentialResponse;
import android.credentials.GetCredentialException;
import android.credentials.GetCredentialResponse;
import android.credentials.GetCredentialResponse;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.service.credentials.CredentialProviderService;
import android.service.credentials.CredentialProviderService;
@@ -31,7 +33,7 @@ import android.service.credentials.CredentialsResponseContent;
 */
 */
public class PendingIntentResultHandler {
public class PendingIntentResultHandler {
    /** Returns true if the result is successful and may contain result extras. */
    /** Returns true if the result is successful and may contain result extras. */
    public static boolean isSuccessfulResponse(
    public static boolean isValidResponse(
            ProviderPendingIntentResponse pendingIntentResponse) {
            ProviderPendingIntentResponse pendingIntentResponse) {
        //TODO: Differentiate based on extra_error in the resultData
        //TODO: Differentiate based on extra_error in the resultData
        return pendingIntentResponse.getResultCode() == Activity.RESULT_OK;
        return pendingIntentResponse.getResultCode() == Activity.RESULT_OK;
@@ -66,4 +68,28 @@ public class PendingIntentResultHandler {
                CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE,
                CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE,
                GetCredentialResponse.class);
                GetCredentialResponse.class);
    }
    }

    /** Extract the {@link CreateCredentialException} from the
     * given pending intent . */
    public static CreateCredentialException extractCreateCredentialException(
            Intent resultData) {
        if (resultData == null) {
            return null;
        }
        return resultData.getParcelableExtra(
                CredentialProviderService.EXTRA_CREATE_CREDENTIAL_EXCEPTION,
                CreateCredentialException.class);
    }

    /** Extract the {@link GetCredentialException} from the
     * given pending intent . */
    public static GetCredentialException extractGetCredentialException(
            Intent resultData) {
        if (resultData == null) {
            return null;
        }
        return resultData.getParcelableExtra(
                CredentialProviderService.EXTRA_GET_CREDENTIAL_EXCEPTION,
                GetCredentialException.class);
    }
}
}
Loading