summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/service/credentials/CredentialProviderErrors.java51
-rw-r--r--core/java/android/service/credentials/CredentialProviderException.java96
-rw-r--r--services/credentials/java/com/android/server/credentials/CreateRequestSession.java51
-rw-r--r--services/credentials/java/com/android/server/credentials/CredentialManagerService.java32
-rw-r--r--services/credentials/java/com/android/server/credentials/GetRequestSession.java37
-rw-r--r--services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java28
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderCreateSession.java72
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderGetSession.java133
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderSession.java13
-rw-r--r--services/credentials/java/com/android/server/credentials/RemoteCredentialService.java30
-rw-r--r--services/credentials/java/com/android/server/credentials/RequestSession.java6
11 files changed, 357 insertions, 192 deletions
diff --git a/core/java/android/service/credentials/CredentialProviderErrors.java b/core/java/android/service/credentials/CredentialProviderErrors.java
new file mode 100644
index 000000000000..e9dc35bc1062
--- /dev/null
+++ b/core/java/android/service/credentials/CredentialProviderErrors.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.credentials;
+
+/**
+ * Contains custom error codes to be used internally for various credential
+ * provider error states.
+ *
+ * @hide
+ */
+public class CredentialProviderErrors {
+ public static final int ERROR_UNKNOWN = 0;
+
+ /**
+ * For internal use only.
+ * Error code to be used when the provider request times out.
+ *
+ * @hide
+ */
+ public static final int ERROR_TIMEOUT = 1;
+
+ /**
+ * For internal use only.
+ * Error code to be used when the async task is canceled internally.
+ *
+ * @hide
+ */
+ public static final int ERROR_TASK_CANCELED = 2;
+
+ /**
+ * For internal use only.
+ * Error code to be used when an exception is received from the provider.
+ *
+ * @hide
+ */
+ public static final int ERROR_PROVIDER_FAILURE = 3;
+}
diff --git a/core/java/android/service/credentials/CredentialProviderException.java b/core/java/android/service/credentials/CredentialProviderException.java
deleted file mode 100644
index 969bcb57ff90..000000000000
--- a/core/java/android/service/credentials/CredentialProviderException.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-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.
- *
- * @hide
- */
-public class CredentialProviderException extends Exception {
- public static final int ERROR_UNKNOWN = 0;
-
- /**
- * For internal use only.
- * Error code to be used when the provider request times out.
- *
- * @hide
- */
- public static final int ERROR_TIMEOUT = 1;
-
- /**
- * For internal use only.
- * Error code to be used when the async task is canceled internally.
- *
- * @hide
- */
- public static final int ERROR_TASK_CANCELED = 2;
-
- /**
- * For internal use only.
- * Error code to be used when the provider encounters a failure while processing the request.
- *
- * @hide
- */
- 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;
- }
-}
diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
index 3d337b896bb7..d9dc4ed6c766 100644
--- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java
@@ -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
public void onProviderStatusChanged(ProviderSession.Status status,
ComponentName componentName) {
@@ -101,10 +91,47 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
@Override
public void onFinalResponseReceived(ComponentName componentName,
- CreateCredentialResponse response) {
+ @Nullable CreateCredentialResponse response) {
Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
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();
}
}
diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
index b4d7632371e7..2c226da72455 100644
--- a/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
+++ b/services/credentials/java/com/android/server/credentials/CredentialManagerService.java
@@ -175,12 +175,20 @@ public final class CredentialManagerService
// Initiate all provider sessions
List<ProviderSession> providerSessions =
- initiateProviderSessions(
- session,
- request.getGetCredentialOptions().stream()
- .map(GetCredentialOption::getType)
- .collect(Collectors.toList()));
- // TODO : Return error when no providers available
+ initiateProviderSessions(session, request.getGetCredentialOptions()
+ .stream().map(GetCredentialOption::getType)
+ .collect(Collectors.toList()));
+
+ 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
providerSessions.forEach(providerGetSession -> {
@@ -212,7 +220,17 @@ public final class CredentialManagerService
// Initiate all provider sessions
List<ProviderSession> providerSessions =
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
providerSessions.forEach(
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index c092b3af9699..6e070f940060 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -88,15 +88,27 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
@Override
public void onFinalResponseReceived(ComponentName componentName,
- GetCredentialResponse response) {
+ @Nullable GetCredentialResponse response) {
Log.i(TAG, "onFinalCredentialReceived from: " + componentName.flattenToString());
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) {
- Log.i(TAG, "respondToClientAndFinish");
+ //TODO: Try moving the three error & response methods below to RequestSession to be shared
+ // 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 {
mClientCallback.onResponse(response);
} catch (RemoteException e) {
@@ -104,4 +116,21 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
}
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");
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
index 7f9e57a5bdb6..8796314b5454 100644
--- a/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
+++ b/services/credentials/java/com/android/server/credentials/PendingIntentResultHandler.java
@@ -18,7 +18,9 @@ package com.android.server.credentials;
import android.app.Activity;
import android.content.Intent;
+import android.credentials.CreateCredentialException;
import android.credentials.CreateCredentialResponse;
+import android.credentials.GetCredentialException;
import android.credentials.GetCredentialResponse;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.service.credentials.CredentialProviderService;
@@ -31,7 +33,7 @@ import android.service.credentials.CredentialsResponseContent;
*/
public class PendingIntentResultHandler {
/** Returns true if the result is successful and may contain result extras. */
- public static boolean isSuccessfulResponse(
+ public static boolean isValidResponse(
ProviderPendingIntentResponse pendingIntentResponse) {
//TODO: Differentiate based on extra_error in the resultData
return pendingIntentResponse.getResultCode() == Activity.RESULT_OK;
@@ -66,4 +68,28 @@ public class PendingIntentResultHandler {
CredentialProviderService.EXTRA_GET_CREDENTIAL_RESPONSE,
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);
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
index 32e85b099c22..855f274d5c98 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderCreateSession.java
@@ -23,6 +23,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.Signature;
+import android.credentials.CreateCredentialException;
import android.credentials.ui.CreateCredentialProviderData;
import android.credentials.ui.Entry;
import android.credentials.ui.ProviderPendingIntentResponse;
@@ -58,6 +59,8 @@ public final class ProviderCreateSession extends ProviderSession<
/** The complete request to be used in the second round. */
private final CreateCredentialRequest mCompleteRequest;
+ private CreateCredentialException mProviderException;
+
/** Creates a new provider session to be used by the request session. */
@Nullable public static ProviderCreateSession createNewSession(
Context context,
@@ -124,8 +127,11 @@ public final class ProviderCreateSession extends ProviderSession<
/** Called when the provider response resulted in a failure. */
@Override
- public void onProviderResponseFailure(int errorCode, @Nullable String errorType,
- @Nullable CharSequence message) {
+ public void onProviderResponseFailure(int errorCode, @Nullable Exception exception) {
+ if (exception instanceof CreateCredentialException) {
+ // Store query phase exception for aggregation with final response
+ mProviderException = (CreateCredentialException) exception;
+ }
updateStatusAndInvokeCallback(toStatus(errorCode));
}
@@ -177,16 +183,20 @@ public final class ProviderCreateSession extends ProviderSession<
if (mUiSaveEntries.containsKey(entryKey)) {
onSaveEntrySelected(providerPendingIntentResponse);
} else {
- //TODO: Handle properly
Log.i(TAG, "Unexpected save entry key");
+ // TODO("Replace with no credentials error type");
+ invokeCallbackWithError("unknown_type",
+ "Issue while retrieving credential");
}
break;
case REMOTE_ENTRY_KEY:
if (mUiRemoteEntry.first.equals(entryKey)) {
onRemoteEntrySelected(providerPendingIntentResponse);
} else {
- //TODO: Handle properly
Log.i(TAG, "Unexpected remote entry key");
+ // TODO("Replace with unknown/no credentials exception")
+ invokeCallbackWithError("unknown_type",
+ "Issue while retrieving credential");
}
break;
default:
@@ -227,19 +237,53 @@ public final class ProviderCreateSession extends ProviderSession<
}
private void onSaveEntrySelected(ProviderPendingIntentResponse pendingIntentResponse) {
- if (pendingIntentResponse == null) {
+ CreateCredentialException exception = maybeGetPendingIntentException(
+ pendingIntentResponse);
+ if (exception != null) {
+ invokeCallbackWithError(
+ exception.errorType,
+ exception.getMessage());
+ return;
+ }
+ android.credentials.CreateCredentialResponse credentialResponse =
+ PendingIntentResultHandler.extractCreateCredentialResponse(
+ pendingIntentResponse.getResultData());
+ if (credentialResponse != null) {
+ mCallbacks.onFinalResponseReceived(mComponentName, credentialResponse);
return;
- //TODO: Handle failure if pending intent is null
+ } else {
+ Log.i(TAG, "onSaveEntrySelected - no response or error found in pending "
+ + "intent response");
+ invokeCallbackWithError(
+ // TODO("Replace with unknown/no credentials exception")
+ "unknown",
+ "Issue encountered while retrieving the credential");
+ }
+ }
+
+ private void invokeCallbackWithError(String errorType, @Nullable String message) {
+ mCallbacks.onFinalErrorReceived(mComponentName, errorType, message);
+ }
+
+ @Nullable
+ private CreateCredentialException maybeGetPendingIntentException(
+ ProviderPendingIntentResponse pendingIntentResponse) {
+ if (pendingIntentResponse == null) {
+ Log.i(TAG, "pendingIntentResponse is null");
+ return null;
}
- if (PendingIntentResultHandler.isSuccessfulResponse(pendingIntentResponse)) {
- android.credentials.CreateCredentialResponse credentialResponse =
- PendingIntentResultHandler.extractCreateCredentialResponse(
- pendingIntentResponse.getResultData());
- if (credentialResponse != null) {
- mCallbacks.onFinalResponseReceived(mComponentName, credentialResponse);
- return;
+ if (PendingIntentResultHandler.isValidResponse(pendingIntentResponse)) {
+ CreateCredentialException exception = PendingIntentResultHandler
+ .extractCreateCredentialException(pendingIntentResponse.getResultData());
+ if (exception != null) {
+ Log.i(TAG, "Pending intent contains provider exception");
+ return exception;
}
+ } else {
+ Log.i(TAG, "Pending intent result code not Activity.RESULT_OK");
+ // TODO("Update with unknown exception when ready")
+ return new CreateCredentialException("unknown");
}
- //TODO: Handle failure case is pending intent response does not have a credential
+ return null;
}
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index f55c457b3122..42f872d2659c 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -22,7 +22,7 @@ import android.annotation.UserIdInt;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.Signature;
+import android.credentials.GetCredentialException;
import android.credentials.GetCredentialOption;
import android.credentials.GetCredentialResponse;
import android.credentials.ui.Entry;
@@ -80,6 +80,8 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
/** The complete request to be used in the second round. */
private final GetCredentialRequest mCompleteRequest;
+ private GetCredentialException mProviderException;
+
/** Creates a new provider session to be used by the request session. */
@Nullable public static ProviderGetSession createNewSession(
Context context,
@@ -131,7 +133,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
if (!filteredOptions.isEmpty()) {
return new GetCredentialRequest.Builder(
new CallingAppInfo(clientCallingPackage,
- new ArraySet<Signature>())).setGetCredentialOptions(
+ new ArraySet<>())).setGetCredentialOptions(
filteredOptions).build();
}
Log.i(TAG, "In createProviderRequest - returning null");
@@ -164,8 +166,10 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
/** Called when the provider response resulted in a failure. */
@Override // Callback from the remote provider
- public void onProviderResponseFailure(int errorCode, @Nullable String errorType,
- @Nullable CharSequence message) {
+ public void onProviderResponseFailure(int errorCode, Exception exception) {
+ if (exception instanceof GetCredentialException) {
+ mProviderException = (GetCredentialException) exception;
+ }
updateStatusAndInvokeCallback(toStatus(errorCode));
}
@@ -187,8 +191,10 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
case CREDENTIAL_ENTRY_KEY:
CredentialEntry credentialEntry = mUiCredentialEntries.get(entryKey);
if (credentialEntry == null) {
- Log.i(TAG, "Credential entry not found");
- //TODO: Handle properly
+ Log.i(TAG, "Unexpected credential entry key");
+ // TODO("Replace with no credentials/unknown exception")
+ invokeCallbackWithError("unknown_type",
+ "Issue while retrieving credential");
return;
}
onCredentialEntrySelected(credentialEntry, providerPendingIntentResponse);
@@ -196,8 +202,10 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
case ACTION_ENTRY_KEY:
Action actionEntry = mUiActionsEntries.get(entryKey);
if (actionEntry == null) {
- Log.i(TAG, "Action entry not found");
- //TODO: Handle properly
+ Log.i(TAG, "Unexpected action entry key");
+ // TODO("Replace with no credentials/unknown exception")
+ invokeCallbackWithError("unknown_type",
+ "Issue while retrieving credential");
return;
}
onActionEntrySelected(providerPendingIntentResponse);
@@ -206,16 +214,20 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
if (mUiAuthenticationAction.first.equals(entryKey)) {
onAuthenticationEntrySelected(providerPendingIntentResponse);
} else {
- //TODO: Handle properly
- Log.i(TAG, "Authentication entry not found");
+ Log.i(TAG, "Unexpected authentication entry key");
+ // TODO("Replace with no credentials/unknown exception")
+ invokeCallbackWithError("unknown_type",
+ "Issue while retrieving credential");
}
break;
case REMOTE_ENTRY_KEY:
if (mUiRemoteEntry.first.equals(entryKey)) {
onRemoteEntrySelected(providerPendingIntentResponse);
} else {
- //TODO: Handle properly
- Log.i(TAG, "Remote entry not found");
+ Log.i(TAG, "Unexpected remote entry key");
+ // TODO("Replace with no credentials/unknown exception")
+ invokeCallbackWithError("unknown_type",
+ "Issue while retrieving credential");
}
break;
default:
@@ -223,6 +235,11 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
}
}
+ private void invokeCallbackWithError(String errorType, @Nullable String errorMessage) {
+ // TODO: Determine what the error message should be
+ mCallbacks.onFinalErrorReceived(mComponentName, errorType, errorMessage);
+ }
+
@Override // Call from request session to data to be shown on the UI
@Nullable protected GetCredentialProviderData prepareUiData() throws IllegalArgumentException {
Log.i(TAG, "In prepareUiData");
@@ -329,39 +346,61 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
private void onCredentialEntrySelected(CredentialEntry credentialEntry,
ProviderPendingIntentResponse providerPendingIntentResponse) {
if (providerPendingIntentResponse != null) {
- if (PendingIntentResultHandler.isSuccessfulResponse(providerPendingIntentResponse)) {
- // TODO: Remove credential extraction when flow is fully transitioned
- GetCredentialResponse getCredentialResponse = PendingIntentResultHandler
- .extractGetCredentialResponse(
- providerPendingIntentResponse.getResultData());
- if (getCredentialResponse != null) {
- mCallbacks.onFinalResponseReceived(mComponentName, getCredentialResponse);
- return;
- }
+ // Check if pending intent has an error
+ GetCredentialException exception = maybeGetPendingIntentException(
+ providerPendingIntentResponse);
+ if (exception != null) {
+ invokeCallbackWithError(exception.errorType,
+ exception.getMessage());
+ return;
}
- // TODO: Handle other pending intent statuses
+
+ // Check if pending intent has a credential
+ GetCredentialResponse getCredentialResponse = PendingIntentResultHandler
+ .extractGetCredentialResponse(
+ providerPendingIntentResponse.getResultData());
+ if (getCredentialResponse != null) {
+ mCallbacks.onFinalResponseReceived(mComponentName,
+ getCredentialResponse);
+ return;
+ }
+
+ Log.i(TAG, "Pending intent response contains no credential, or error");
+ // TODO("Replace with no credentials/unknown error when ready)
+ invokeCallbackWithError("unknown_type",
+ "Issue while retrieving credential");
}
Log.i(TAG, "CredentialEntry does not have a credential or a pending intent result");
- // TODO: Propagate failure to client
+ // TODO("Replace with no credentials/unknown error when ready)
+ invokeCallbackWithError("unknown_type",
+ "Error encountered while retrieving the credential");
}
private void onAuthenticationEntrySelected(
@Nullable ProviderPendingIntentResponse providerPendingIntentResponse) {
- if (providerPendingIntentResponse != null) {
- if (PendingIntentResultHandler.isSuccessfulResponse(providerPendingIntentResponse)) {
- CredentialsResponseContent content = PendingIntentResultHandler
- .extractResponseContent(providerPendingIntentResponse
- .getResultData());
- if (content != null) {
- onUpdateResponse(
- BeginGetCredentialResponse.createWithResponseContent(content));
- return;
- }
- }
//TODO: Other provider intent statuses
+ // Check if pending intent has an error
+ GetCredentialException exception = maybeGetPendingIntentException(
+ providerPendingIntentResponse);
+ if (exception != null) {
+ invokeCallbackWithError(exception.errorType,
+ exception.getMessage());
+ return;
}
- Log.i(TAG, "Display content not present in pending intent result");
- // TODO: Propagate error to client
+
+ // Check if pending intent has the content
+ CredentialsResponseContent content = PendingIntentResultHandler
+ .extractResponseContent(providerPendingIntentResponse
+ .getResultData());
+ if (content != null) {
+ onUpdateResponse(BeginGetCredentialResponse.createWithResponseContent(content));
+ return;
+ }
+
+ Log.i(TAG, "No error or respond found in pending intent response");
+ // TODO("Replace with no credentials/unknown error when ready)
+ invokeCallbackWithError("unknown type", "Issue"
+ + " while retrieving credential");
}
private void onActionEntrySelected(ProviderPendingIntentResponse
@@ -382,4 +421,26 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
}
}
+
+ @Nullable
+ private GetCredentialException maybeGetPendingIntentException(
+ ProviderPendingIntentResponse pendingIntentResponse) {
+ if (pendingIntentResponse == null) {
+ Log.i(TAG, "pendingIntentResponse is null");
+ return null;
+ }
+ if (PendingIntentResultHandler.isValidResponse(pendingIntentResponse)) {
+ GetCredentialException exception = PendingIntentResultHandler
+ .extractGetCredentialException(pendingIntentResponse.getResultData());
+ if (exception != null) {
+ Log.i(TAG, "Pending intent contains provider exception");
+ return exception;
+ }
+ } else {
+ Log.i(TAG, "Pending intent result code not Activity.RESULT_OK");
+ // TODO("Update with unknown exception when ready")
+ return new GetCredentialException("unknown");
+ }
+ return null;
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index ac360bd4fc9e..7ecae9d3bec9 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -24,7 +24,6 @@ import android.credentials.Credential;
import android.credentials.ui.ProviderData;
import android.credentials.ui.ProviderPendingIntentResponse;
import android.service.credentials.CredentialEntry;
-import android.service.credentials.CredentialProviderException;
import android.service.credentials.CredentialProviderInfo;
import android.util.Pair;
@@ -37,6 +36,8 @@ import java.util.UUID;
*/
public abstract class ProviderSession<T, R>
implements RemoteCredentialService.ProviderCallbacks<R> {
+
+ private static final String TAG = "ProviderSession";
// Key to be used as an entry key for a remote entry
protected static final String REMOTE_ENTRY_KEY = "remote_entry_key";
@@ -52,6 +53,7 @@ public abstract class ProviderSession<T, R>
@Nullable protected R mProviderResponse;
@Nullable protected Pair<String, CredentialEntry> mUiRemoteEntry;
+
/**
* Returns true if the given status reflects that the provider state is ready to be shown
* on the credMan UI.
@@ -95,8 +97,12 @@ public abstract class ProviderSession<T, R>
/** Called when status changes. */
void onProviderStatusChanged(Status status, ComponentName componentName);
- /** Called when the final credential to be returned to the client has been received. */
+ /** Called when the final credential is received through an entry selection. */
void onFinalResponseReceived(ComponentName componentName, V response);
+
+ /** Called when an error is received through an entry selection. */
+ void onFinalErrorReceived(ComponentName componentName, String errorType,
+ @Nullable String message);
}
protected ProviderSession(@NonNull Context context, @NonNull CredentialProviderInfo info,
@@ -129,8 +135,7 @@ public abstract class ProviderSession<T, R>
/** Converts exception to a provider session status. */
@NonNull
- public static Status toStatus(
- @CredentialProviderException.CredentialProviderError int errorCode) {
+ public static Status toStatus(int errorCode) {
// TODO : Add more mappings as more flows are supported
return Status.CANCELED;
}
diff --git a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
index 307d96a3bded..6049fd9a4a21 100644
--- a/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
+++ b/services/credentials/java/com/android/server/credentials/RemoteCredentialService.java
@@ -30,7 +30,7 @@ import android.service.credentials.BeginCreateCredentialRequest;
import android.service.credentials.BeginCreateCredentialResponse;
import android.service.credentials.BeginGetCredentialRequest;
import android.service.credentials.BeginGetCredentialResponse;
-import android.service.credentials.CredentialProviderException;
+import android.service.credentials.CredentialProviderErrors;
import android.service.credentials.CredentialProviderService;
import android.service.credentials.IBeginCreateCredentialCallback;
import android.service.credentials.IBeginGetCredentialCallback;
@@ -72,8 +72,7 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
/** Called when a successful response is received from the remote provider. */
void onProviderResponseSuccess(@Nullable T response);
/** Called when a failure response is received from the remote provider. */
- void onProviderResponseFailure(int errorCode, @Nullable String errorType,
- @Nullable CharSequence message);
+ void onProviderResponseFailure(int internalErrorCode, @Nullable Exception e);
/** Called when the remote provider service dies. */
void onProviderServiceDied(RemoteCredentialService service);
}
@@ -208,36 +207,31 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
Log.i(TAG, "In RemoteCredentialService execute error is timeout");
dispatchCancellationSignal(cancellationSink.get());
callback.onProviderResponseFailure(
- CredentialProviderException.ERROR_TIMEOUT,
- null,
- error.getMessage());
+ CredentialProviderErrors.ERROR_TIMEOUT,
+ null);
} else if (error instanceof CancellationException) {
Log.i(TAG, "In RemoteCredentialService execute error is cancellation");
dispatchCancellationSignal(cancellationSink.get());
callback.onProviderResponseFailure(
- CredentialProviderException.ERROR_TASK_CANCELED,
- null,
- error.getMessage());
+ CredentialProviderErrors.ERROR_TASK_CANCELED,
+ null);
} else if (error instanceof GetCredentialException) {
Log.i(TAG, "In RemoteCredentialService execute error is provider get"
+ "error");
callback.onProviderResponseFailure(
- CredentialProviderException.ERROR_PROVIDER_FAILURE,
- ((GetCredentialException) error).errorType,
- error.getMessage());
+ CredentialProviderErrors.ERROR_PROVIDER_FAILURE,
+ (GetCredentialException) error);
} else if (error instanceof CreateCredentialException) {
Log.i(TAG, "In RemoteCredentialService execute error is provider create "
+ "error");
callback.onProviderResponseFailure(
- CredentialProviderException.ERROR_PROVIDER_FAILURE,
- ((CreateCredentialException) error).errorType,
- error.getMessage());
+ CredentialProviderErrors.ERROR_PROVIDER_FAILURE,
+ (CreateCredentialException) error);
} else {
Log.i(TAG, "In RemoteCredentialService execute error is unknown");
callback.onProviderResponseFailure(
- CredentialProviderException.ERROR_UNKNOWN,
- null,
- error.getMessage());
+ CredentialProviderErrors.ERROR_UNKNOWN,
+ (Exception) error);
}
}
}
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index 71fc67ce5afd..937fac98a0b3 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -93,6 +93,7 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
@Override // from CredentialManagerUiCallbacks
public void onUiCancellation() {
+ Log.i(TAG, "Ui canceled");
// User canceled the activity
finishSession();
}
@@ -133,10 +134,12 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
}
protected void finishSession() {
+ Log.i(TAG, "finishing session");
clearProviderSessions();
}
protected void clearProviderSessions() {
+ Log.i(TAG, "Clearing sessions");
//TODO: Implement
mProviders.clear();
}
@@ -151,6 +154,9 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
}
private void getProviderDataAndInitiateUi() {
+ Log.i(TAG, "In getProviderDataAndInitiateUi");
+ Log.i(TAG, "In getProviderDataAndInitiateUi providers size: " + mProviders.size());
+
ArrayList<ProviderData> providerDataList = new ArrayList<>();
for (ProviderSession session : mProviders.values()) {
Log.i(TAG, "preparing data for : " + session.getComponentName());