Make ProviderRegistryGetSesh per option.

Make sure that ProviderRegistryGetSessions are
created for each CredentialOption sent with
the GetCredentialRequest.

Bug: 269800380
Test: manual
Change-Id: I9701ac6b971789751d2d63804c19258b22f4f35b
This commit is contained in:
Omer Ozer
2023-02-16 19:42:08 +00:00
parent e1295fff9c
commit 2a401d42db
3 changed files with 56 additions and 55 deletions

View File

@@ -49,11 +49,14 @@ public final class CredentialDescriptionRegistry {
/** Represents the results of a given query into the registry. */
public static final class FilterResult {
final String mPackageName;
final String mFlattenedRequest;
final List<CredentialEntry> mCredentialEntries;
private FilterResult(String packageName,
String flattenedRequest,
List<CredentialEntry> credentialEntries) {
mPackageName = packageName;
mFlattenedRequest = flattenedRequest;
mCredentialEntries = credentialEntries;
}
}
@@ -133,12 +136,13 @@ public final class CredentialDescriptionRegistry {
/** Returns package names and entries of a CredentialProviders that can satisfy a given
* {@link CredentialDescription}. */
public Set<FilterResult> getFilteredResultForProvider(String packageName,
List<String> flatRequestStrings) {
String flatRequestStrings) {
Set<FilterResult> result = new HashSet<>();
Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
for (CredentialDescription containedDescription: currentSet) {
if (flatRequestStrings.contains(containedDescription.getFlattenedRequestString())) {
result.add(new FilterResult(packageName, containedDescription
if (flatRequestStrings.equals(containedDescription.getFlattenedRequestString())) {
result.add(new FilterResult(packageName,
containedDescription.getFlattenedRequestString(), containedDescription
.getCredentialEntries()));
}
}
@@ -147,13 +151,15 @@ public final class CredentialDescriptionRegistry {
/** Returns package names of CredentialProviders that can satisfy a given
* {@link CredentialDescription}. */
public Set<String> getMatchingProviders(Set<String> flatRequestString) {
Set<String> result = new HashSet<>();
public Set<FilterResult> getMatchingProviders(Set<String> flatRequestString) {
Set<FilterResult> result = new HashSet<>();
for (String packageName: mCredentialDescriptions.keySet()) {
Set<CredentialDescription> currentSet = mCredentialDescriptions.get(packageName);
for (CredentialDescription containedDescription : currentSet) {
if (flatRequestString.contains(containedDescription.getFlattenedRequestString())) {
result.add(packageName);
result.add(new FilterResult(packageName,
containedDescription.getFlattenedRequestString(), containedDescription
.getCredentialEntries()));
}
}
}

View File

@@ -58,6 +58,7 @@ import android.service.credentials.CallingAppInfo;
import android.service.credentials.CredentialProviderInfo;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
@@ -66,6 +67,7 @@ import com.android.server.infra.AbstractMasterSystemService;
import com.android.server.infra.SecureSettingsServiceNameResolver;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -274,24 +276,25 @@ public final class CredentialManagerService
// to be guarded by 'service.mLock', which is the same as mLock.
private List<ProviderSession> initiateProviderSessionsWithActiveContainers(
GetRequestSession session,
List<String> requestOptions,
Set<String> activeCredentialContainers) {
Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>>
activeCredentialContainers) {
List<ProviderSession> providerSessions = new ArrayList<>();
// Invoke all services of a user to initiate a provider session
for (String packageName : activeCredentialContainers) {
for (Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult> result :
activeCredentialContainers) {
providerSessions.add(
ProviderRegistryGetSession.createNewSession(
mContext,
UserHandle.getCallingUserId(),
session,
packageName,
requestOptions));
result.second.mPackageName,
result.first));
}
return providerSessions;
}
@NonNull
private Set<String> getFilteredResultFromRegistry(List<CredentialOption> options) {
private Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>>
getFilteredResultFromRegistry(List<CredentialOption> options) {
// Session for active/provisioned credential descriptions;
CredentialDescriptionRegistry registry =
CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
@@ -307,7 +310,22 @@ public final class CredentialManagerService
.collect(Collectors.toSet());
// All requested credential descriptions based on the given request.
return registry.getMatchingProviders(requestedCredentialDescriptions);
Set<CredentialDescriptionRegistry.FilterResult> filterResults =
registry.getMatchingProviders(requestedCredentialDescriptions);
Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>> result =
new HashSet<>();
for (CredentialDescriptionRegistry.FilterResult filterResult: filterResults) {
for (CredentialOption credentialOption: options) {
if (filterResult.mFlattenedRequest.equals(credentialOption
.getCredentialRetrievalData()
.getString(CredentialOption.FLATTENED_REQUEST))) {
result.add(new Pair<>(credentialOption, filterResult));
}
}
}
return result;
}
@SuppressWarnings("GuardedBy") // ErrorProne requires initiateProviderSessionForRequestLocked
@@ -452,15 +470,6 @@ public final class CredentialManagerService
List<ProviderSession> sessionsWithoutRemoteService =
initiateProviderSessionsWithActiveContainers(
session,
optionsThatRequireActiveCredentials.stream()
.map(
getCredentialOption ->
getCredentialOption
.getCredentialRetrievalData()
.getString(
CredentialOption
.FLATTENED_REQUEST))
.collect(Collectors.toList()),
getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
List<ProviderSession> sessionsWithRemoteService =

View File

@@ -23,7 +23,6 @@ import android.content.Context;
import android.content.Intent;
import android.credentials.CredentialOption;
import android.credentials.GetCredentialException;
import android.credentials.GetCredentialRequest;
import android.credentials.GetCredentialResponse;
import android.credentials.ui.Entry;
import android.credentials.ui.GetCredentialProviderData;
@@ -49,7 +48,7 @@ import java.util.stream.Stream;
*
* @hide
*/
public class ProviderRegistryGetSession extends ProviderSession<GetCredentialRequest,
public class ProviderRegistryGetSession extends ProviderSession<CredentialOption,
Set<CredentialDescriptionRegistry.FilterResult>> {
private static final String TAG = "ProviderRegistryGetSession";
@@ -62,15 +61,14 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
@UserIdInt int userId,
@NonNull GetRequestSession getRequestSession,
@NonNull String credentialProviderPackageName,
@NonNull List<String> requestOptions) {
@NonNull CredentialOption requestOption) {
return new ProviderRegistryGetSession(
context,
userId,
getRequestSession,
getRequestSession.mClientRequest,
getRequestSession.mClientAppInfo,
credentialProviderPackageName,
requestOptions);
requestOption);
}
@NonNull
@@ -82,24 +80,22 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
@NonNull
private final String mCredentialProviderPackageName;
@NonNull
private final GetRequestSession mGetRequestSession;
@NonNull
private final List<String> mRequestOptions;
private final String mFlattenedRequestOptionString;
private List<CredentialEntry> mCredentialEntries;
protected ProviderRegistryGetSession(@NonNull Context context,
@NonNull int userId,
@NonNull GetRequestSession session,
@NonNull GetCredentialRequest request,
@NonNull CallingAppInfo callingAppInfo,
@NonNull String servicePackageName,
@NonNull List<String> requestOptions) {
super(context, null, request, session, userId, null);
mGetRequestSession = session;
@NonNull CredentialOption requestOption) {
super(context, null, requestOption, session, userId, null);
mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId);
mCallingAppInfo = callingAppInfo;
mCredentialProviderPackageName = servicePackageName;
mRequestOptions = requestOptions;
mFlattenedRequestOptionString = requestOption
.getCredentialRetrievalData()
.getString(CredentialOption.FLATTENED_REQUEST);
}
private List<Entry> prepareUiCredentialEntries(
@@ -114,23 +110,18 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
credentialUiEntries.add(new Entry(CREDENTIAL_ENTRY_KEY, entryId,
credentialEntry.getSlice(),
setUpFillInIntent(credentialEntry.getType())));
setUpFillInIntent()));
}
return credentialUiEntries;
}
private Intent setUpFillInIntent(String type) {
private Intent setUpFillInIntent() {
Intent intent = new Intent();
for (CredentialOption option : mProviderRequest.getCredentialOptions()) {
if (option.getType().equals(type)) {
intent.putExtra(
CredentialProviderService
.EXTRA_GET_CREDENTIAL_REQUEST,
new android.service.credentials.GetCredentialRequest(
mCallingAppInfo, option));
return intent;
}
}
intent.putExtra(
CredentialProviderService
.EXTRA_GET_CREDENTIAL_REQUEST,
new android.service.credentials.GetCredentialRequest(
mCallingAppInfo, mProviderRequest));
return intent;
}
@@ -176,11 +167,6 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
private void onCredentialEntrySelected(CredentialEntry credentialEntry,
ProviderPendingIntentResponse providerPendingIntentResponse) {
if (!mCredentialEntries.contains(credentialEntry)) {
invokeCallbackWithError("",
"");
}
if (providerPendingIntentResponse != null) {
// Check if pending intent has an error
GetCredentialException exception = maybeGetPendingIntentException(
@@ -228,13 +214,13 @@ public class ProviderRegistryGetSession extends ProviderSession<GetCredentialReq
protected void invokeSession() {
mProviderResponse = mCredentialDescriptionRegistry
.getFilteredResultForProvider(mCredentialProviderPackageName,
mRequestOptions);
mFlattenedRequestOptionString);
mCredentialEntries = mProviderResponse.stream().flatMap(
(Function<CredentialDescriptionRegistry.FilterResult,
Stream<CredentialEntry>>) filterResult
-> filterResult.mCredentialEntries.stream())
.collect(Collectors.toList());
setStatus(Status.CREDENTIALS_RECEIVED);
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
// TODO(use metric later)
}