summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/credentials/java/com/android/server/credentials/GetRequestSession.java37
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderGetSession.java35
-rw-r--r--services/credentials/java/com/android/server/credentials/ProviderSession.java5
-rw-r--r--services/credentials/java/com/android/server/credentials/RequestSession.java2
4 files changed, 71 insertions, 8 deletions
diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
index 5e167712a8e8..32b14d773b95 100644
--- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java
@@ -44,7 +44,6 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
IGetCredentialCallback>
implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
private static final String TAG = "GetRequestSession";
-
public GetRequestSession(Context context, int userId, int callingUid,
IGetCredentialCallback callback, GetCredentialRequest request,
CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal) {
@@ -173,6 +172,12 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
public void onProviderStatusChanged(ProviderSession.Status status,
ComponentName componentName) {
Log.i(TAG, "in onStatusChanged with status: " + status);
+ // Auth entry was selected, and it did not have any underlying credentials
+ if (status == ProviderSession.Status.NO_CREDENTIALS_FROM_AUTH_ENTRY) {
+ handleEmptyAuthenticationSelection(componentName);
+ return;
+ }
+ // For any other status, we check if all providers are done and then invoke UI if needed
if (!isAnyProviderPending()) {
// If all provider responses have been received, we can either need the UI,
// or we need to respond with error. The only other case is the entry being
@@ -186,4 +191,34 @@ public final class GetRequestSession extends RequestSession<GetCredentialRequest
}
}
}
+
+ private void handleEmptyAuthenticationSelection(ComponentName componentName) {
+ // Update auth entry statuses across different provider sessions
+ mProviders.keySet().forEach(key -> {
+ ProviderGetSession session = (ProviderGetSession) mProviders.get(key);
+ if (!session.mComponentName.equals(componentName)) {
+ session.updateAuthEntriesStatusFromAnotherSession();
+ }
+ });
+
+ // Invoke UI since it needs to show a snackbar if last auth entry, or a status on each
+ // auth entries along with other valid entries
+ getProviderDataAndInitiateUi();
+
+ // Respond to client if all auth entries are empty and nothing else to show on the UI
+ if (providerDataContainsEmptyAuthEntriesOnly()) {
+ respondToClientWithErrorAndFinish(GetCredentialException.TYPE_NO_CREDENTIAL,
+ "No credentials available");
+ }
+ }
+
+ private boolean providerDataContainsEmptyAuthEntriesOnly() {
+ for (String key : mProviders.keySet()) {
+ ProviderGetSession session = (ProviderGetSession) mProviders.get(key);
+ if (!session.containsEmptyAuthEntriesOnly()) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
index 12074c7494bf..8c94b0ada2a8 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderGetSession.java
@@ -241,13 +241,14 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
if (additionalContentReceived) {
Log.i(TAG, "Additional content received - removing authentication entry");
mProviderResponseDataHandler.removeAuthenticationAction(entryKey);
+ if (!mProviderResponseDataHandler.isEmptyResponse()) {
+ updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
+ }
} else {
Log.i(TAG, "Additional content not received");
mProviderResponseDataHandler
.updateAuthEntryWithNoCredentialsReceived(entryKey);
- }
- if (!mProviderResponseDataHandler.isEmptyResponse()) {
- updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
+ updateStatusAndInvokeCallback(Status.NO_CREDENTIALS_FROM_AUTH_ENTRY);
}
break;
case REMOTE_ENTRY_KEY:
@@ -456,6 +457,27 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
GetCredentialException.TYPE_UNKNOWN, null);
}
+ /** Update auth entries status based on an auth entry selected from a different session. */
+ public void updateAuthEntriesStatusFromAnotherSession() {
+ // Pass null for entryKey if the auth entry selected belongs to a different session
+ mProviderResponseDataHandler.updateAuthEntryWithNoCredentialsReceived(/*entryKey=*/null);
+ }
+
+ /** Returns true if the provider response contains empty auth entries only, false otherwise. **/
+ public boolean containsEmptyAuthEntriesOnly() {
+ // We do not consider action entries here because if actions are the only entries,
+ // we don't show the UI
+ return mProviderResponseDataHandler.mUiCredentialEntries.isEmpty()
+ && mProviderResponseDataHandler.mUiRemoteEntry == null
+ && mProviderResponseDataHandler.mUiAuthenticationEntries
+ .values().stream().allMatch(
+ e -> e.second.getStatus() == AuthenticationEntry
+ .STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT
+ || e.second.getStatus()
+ == AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT
+ );
+ }
+
private class ProviderResponseDataHandler {
private final ComponentName mExpectedRemoteEntryProviderService;
@NonNull
@@ -610,7 +632,12 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
? null : mUiCredentialEntries.get(entryKey).first;
}
- public void updateAuthEntryWithNoCredentialsReceived(String entryKey) {
+ public void updateAuthEntryWithNoCredentialsReceived(@Nullable String entryKey) {
+ if (entryKey == null) {
+ // Auth entry from a different provider was selected by the user.
+ updatePreviousMostRecentAuthEntry();
+ return;
+ }
updatePreviousMostRecentAuthEntry();
updateMostRecentAuthEntry(entryKey);
}
diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java
index 2f9d57872c3c..ecddcf30f88d 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java
@@ -66,7 +66,8 @@ public abstract class ProviderSession<T, R>
* on the credMan UI.
*/
public static boolean isUiInvokingStatus(Status status) {
- return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED;
+ return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED
+ || status == Status.NO_CREDENTIALS_FROM_AUTH_ENTRY;
}
/**
@@ -140,7 +141,7 @@ public abstract class ProviderSession<T, R>
PENDING_INTENT_INVOKED,
CREDENTIAL_RECEIVED_FROM_SELECTION,
SAVE_ENTRIES_RECEIVED, CANCELED,
- NO_CREDENTIALS, EMPTY_RESPONSE, COMPLETE
+ NO_CREDENTIALS, EMPTY_RESPONSE, NO_CREDENTIALS_FROM_AUTH_ENTRY, COMPLETE
}
/** Converts exception to a provider session status. */
diff --git a/services/credentials/java/com/android/server/credentials/RequestSession.java b/services/credentials/java/com/android/server/credentials/RequestSession.java
index f0d05c5dfd05..f8bbfcfb6a4d 100644
--- a/services/credentials/java/com/android/server/credentials/RequestSession.java
+++ b/services/credentials/java/com/android/server/credentials/RequestSession.java
@@ -216,7 +216,7 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
* Returns true if at least one provider is ready for UI invocation, and no
* provider is pending a response.
*/
- boolean isUiInvocationNeeded() {
+ protected boolean isUiInvocationNeeded() {
for (ProviderSession session : mProviders.values()) {
if (ProviderSession.isUiInvokingStatus(session.getStatus())) {
return true;