Allow retainning entries across selections
Authentication entries are now being set with the right status Test: built locally Bug: 268505084 Change-Id: I1b47b1485f568c649daa5a1ca59f180b83a721e9
This commit is contained in:
@@ -19,6 +19,7 @@ package com.android.server.credentials;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.credentials.CreateCredentialException;
|
||||
@@ -56,14 +57,11 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
// Key to be used as an entry key for a remote entry
|
||||
private static final String REMOTE_ENTRY_KEY = "remote_entry_key";
|
||||
|
||||
@NonNull
|
||||
private final Map<String, CreateEntry> mUiSaveEntries = new HashMap<>();
|
||||
/** The complete request to be used in the second round. */
|
||||
private final CreateCredentialRequest mCompleteRequest;
|
||||
|
||||
private CreateCredentialException mProviderException;
|
||||
|
||||
@Nullable protected Pair<String, CreateEntry> mUiRemoteEntry;
|
||||
private final ProviderResponseDataHandler mProviderResponseDataHandler;
|
||||
|
||||
/** Creates a new provider session to be used by the request session. */
|
||||
@Nullable public static ProviderCreateSession createNewSession(
|
||||
@@ -88,7 +86,8 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
createRequestSession.mClientAppInfo,
|
||||
createRequestSession
|
||||
.mClientRequest.alwaysSendAppInfoToProvider()),
|
||||
providerCreateRequest
|
||||
providerCreateRequest,
|
||||
createRequestSession.mHybridService
|
||||
);
|
||||
}
|
||||
Log.i(TAG, "Unable to create provider session");
|
||||
@@ -131,23 +130,20 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
@UserIdInt int userId,
|
||||
@NonNull RemoteCredentialService remoteCredentialService,
|
||||
@NonNull BeginCreateCredentialRequest beginCreateRequest,
|
||||
@NonNull CreateCredentialRequest completeCreateRequest) {
|
||||
@NonNull CreateCredentialRequest completeCreateRequest,
|
||||
String hybridService) {
|
||||
super(context, info, beginCreateRequest, callbacks, userId,
|
||||
remoteCredentialService);
|
||||
mCompleteRequest = completeCreateRequest;
|
||||
setStatus(Status.PENDING);
|
||||
}
|
||||
|
||||
/** Returns the save entry maintained in state by this provider session. */
|
||||
public CreateEntry getUiSaveEntry(String entryId) {
|
||||
return mUiSaveEntries.get(entryId);
|
||||
mProviderResponseDataHandler = new ProviderResponseDataHandler(hybridService);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderResponseSuccess(
|
||||
@Nullable BeginCreateCredentialResponse response) {
|
||||
Log.i(TAG, "in onProviderResponseSuccess");
|
||||
onUpdateResponse(response);
|
||||
onSetInitialRemoteResponse(response);
|
||||
}
|
||||
|
||||
/** Called when the provider response resulted in a failure. */
|
||||
@@ -171,21 +167,18 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
}
|
||||
}
|
||||
|
||||
private void onUpdateResponse(BeginCreateCredentialResponse response) {
|
||||
Log.i(TAG, "updateResponse with save entries");
|
||||
private void onSetInitialRemoteResponse(BeginCreateCredentialResponse response) {
|
||||
Log.i(TAG, "onSetInitialRemoteResponse with save entries");
|
||||
mProviderResponse = response;
|
||||
if (isEmptyResponse(response)) {
|
||||
mProviderResponseDataHandler.addResponseContent(response.getCreateEntries(),
|
||||
response.getRemoteCreateEntry());
|
||||
if (mProviderResponseDataHandler.isEmptyResponse(response)) {
|
||||
updateStatusAndInvokeCallback(Status.EMPTY_RESPONSE);
|
||||
} else {
|
||||
updateStatusAndInvokeCallback(Status.SAVE_ENTRIES_RECEIVED);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmptyResponse(BeginCreateCredentialResponse response) {
|
||||
return (response.getCreateEntries() == null || response.getCreateEntries().isEmpty())
|
||||
&& response.getRemoteCreateEntry() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable protected CreateCredentialProviderData prepareUiData()
|
||||
throws IllegalArgumentException {
|
||||
@@ -194,53 +187,37 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
Log.i(TAG, "In prepareUiData not in uiInvokingStatus");
|
||||
return null;
|
||||
}
|
||||
final BeginCreateCredentialResponse response = getProviderResponse();
|
||||
if (response == null) {
|
||||
Log.i(TAG, "In prepareUiData response null");
|
||||
throw new IllegalStateException("Response must be in completion mode");
|
||||
}
|
||||
if (response.getCreateEntries() != null) {
|
||||
|
||||
if (mProviderResponse != null && !mProviderResponseDataHandler.isEmptyResponse()) {
|
||||
Log.i(TAG, "In prepareUiData save entries not null");
|
||||
return prepareUiProviderData(
|
||||
prepareUiSaveEntries(response.getCreateEntries()),
|
||||
prepareUiRemoteEntry(response.getRemoteCreateEntry()));
|
||||
return mProviderResponseDataHandler.toCreateCredentialProviderData();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Entry prepareUiRemoteEntry(CreateEntry remoteCreateEntry) {
|
||||
if (remoteCreateEntry == null) {
|
||||
return null;
|
||||
}
|
||||
String entryId = generateUniqueId();
|
||||
Entry remoteEntry = new Entry(REMOTE_ENTRY_KEY, entryId, remoteCreateEntry.getSlice(),
|
||||
setUpFillInIntent());
|
||||
mUiRemoteEntry = new Pair<>(entryId, remoteCreateEntry);
|
||||
return remoteEntry;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUiEntrySelected(String entryType, String entryKey,
|
||||
ProviderPendingIntentResponse providerPendingIntentResponse) {
|
||||
switch (entryType) {
|
||||
case SAVE_ENTRY_KEY:
|
||||
if (mUiSaveEntries.containsKey(entryKey)) {
|
||||
onSaveEntrySelected(providerPendingIntentResponse);
|
||||
} else {
|
||||
if (mProviderResponseDataHandler.getCreateEntry(entryKey) == null) {
|
||||
Log.i(TAG, "Unexpected save entry key");
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
return;
|
||||
}
|
||||
onCreateEntrySelected(providerPendingIntentResponse);
|
||||
break;
|
||||
case REMOTE_ENTRY_KEY:
|
||||
if (mUiRemoteEntry.first.equals(entryKey)) {
|
||||
onRemoteEntrySelected(providerPendingIntentResponse);
|
||||
} else {
|
||||
if (mProviderResponseDataHandler.getRemoteEntry(entryKey) == null) {
|
||||
Log.i(TAG, "Unexpected remote entry key");
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
return;
|
||||
}
|
||||
onRemoteEntrySelected(providerPendingIntentResponse);
|
||||
break;
|
||||
default:
|
||||
Log.i(TAG, "Unsupported entry type selected");
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,21 +229,6 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
}
|
||||
}
|
||||
|
||||
private List<Entry> prepareUiSaveEntries(@NonNull List<CreateEntry> saveEntries) {
|
||||
Log.i(TAG, "in populateUiSaveEntries");
|
||||
List<Entry> uiSaveEntries = new ArrayList<>();
|
||||
|
||||
// Populate the save entries
|
||||
for (CreateEntry createEntry : saveEntries) {
|
||||
String entryId = generateUniqueId();
|
||||
mUiSaveEntries.put(entryId, createEntry);
|
||||
Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
|
||||
uiSaveEntries.add(new Entry(SAVE_ENTRY_KEY, entryId, createEntry.getSlice(),
|
||||
setUpFillInIntent()));
|
||||
}
|
||||
return uiSaveEntries;
|
||||
}
|
||||
|
||||
private Intent setUpFillInIntent() {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(CredentialProviderService.EXTRA_CREATE_CREDENTIAL_REQUEST,
|
||||
@@ -274,16 +236,7 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
return intent;
|
||||
}
|
||||
|
||||
private CreateCredentialProviderData prepareUiProviderData(List<Entry> saveEntries,
|
||||
Entry remoteEntry) {
|
||||
return new CreateCredentialProviderData.Builder(
|
||||
mComponentName.flattenToString())
|
||||
.setSaveEntries(saveEntries)
|
||||
.setRemoteEntry(remoteEntry)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void onSaveEntrySelected(ProviderPendingIntentResponse pendingIntentResponse) {
|
||||
private void onCreateEntrySelected(ProviderPendingIntentResponse pendingIntentResponse) {
|
||||
CreateCredentialException exception = maybeGetPendingIntentException(
|
||||
pendingIntentResponse);
|
||||
if (exception != null) {
|
||||
@@ -297,7 +250,6 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
pendingIntentResponse.getResultData());
|
||||
if (credentialResponse != null) {
|
||||
mCallbacks.onFinalResponseReceived(mComponentName, credentialResponse);
|
||||
return;
|
||||
} else {
|
||||
Log.i(TAG, "onSaveEntrySelected - no response or error found in pending "
|
||||
+ "intent response");
|
||||
@@ -305,6 +257,12 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
}
|
||||
}
|
||||
|
||||
private void onRemoteEntrySelected(ProviderPendingIntentResponse pendingIntentResponse) {
|
||||
// Response from remote entry should be dealt with similar to a response from a
|
||||
// create entry
|
||||
onCreateEntrySelected(pendingIntentResponse);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private CreateCredentialException maybeGetPendingIntentException(
|
||||
ProviderPendingIntentResponse pendingIntentResponse) {
|
||||
@@ -336,4 +294,91 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
CreateCredentialException.TYPE_UNKNOWN,
|
||||
null);
|
||||
}
|
||||
|
||||
private class ProviderResponseDataHandler {
|
||||
private final ComponentName mExpectedRemoteEntryProviderService;
|
||||
|
||||
@NonNull
|
||||
private final Map<String, Pair<CreateEntry, Entry>> mUiCreateEntries = new HashMap<>();
|
||||
|
||||
@Nullable private Pair<String, Pair<CreateEntry, Entry>> mUiRemoteEntry = null;
|
||||
|
||||
ProviderResponseDataHandler(String hybridService) {
|
||||
mExpectedRemoteEntryProviderService = ComponentName.unflattenFromString(hybridService);
|
||||
}
|
||||
|
||||
public void addResponseContent(List<CreateEntry> createEntries,
|
||||
CreateEntry remoteEntry) {
|
||||
createEntries.forEach(this::addCreateEntry);
|
||||
setRemoteEntry(remoteEntry);
|
||||
}
|
||||
public void addCreateEntry(CreateEntry createEntry) {
|
||||
String id = generateUniqueId();
|
||||
Entry entry = new Entry(SAVE_ENTRY_KEY,
|
||||
id, createEntry.getSlice(), setUpFillInIntent());
|
||||
mUiCreateEntries.put(id, new Pair<>(createEntry, entry));
|
||||
}
|
||||
|
||||
public void setRemoteEntry(@Nullable CreateEntry remoteEntry) {
|
||||
if (remoteEntry == null) {
|
||||
mUiRemoteEntry = null;
|
||||
return;
|
||||
}
|
||||
if (!mComponentName.equals(mExpectedRemoteEntryProviderService)) {
|
||||
Log.i(TAG, "Remote entry being dropped as it is not from the service "
|
||||
+ "configured by the OEM.");
|
||||
return;
|
||||
}
|
||||
String id = generateUniqueId();
|
||||
Entry entry = new Entry(REMOTE_ENTRY_KEY,
|
||||
id, remoteEntry.getSlice(), setUpFillInIntent());
|
||||
mUiRemoteEntry = new Pair<>(id, new Pair<>(remoteEntry, entry));
|
||||
}
|
||||
|
||||
public CreateCredentialProviderData toCreateCredentialProviderData() {
|
||||
return new CreateCredentialProviderData.Builder(
|
||||
mComponentName.flattenToString())
|
||||
.setSaveEntries(prepareUiCreateEntries())
|
||||
.setRemoteEntry(prepareRemoteEntry())
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<Entry> prepareUiCreateEntries() {
|
||||
List<Entry> createEntries = new ArrayList<>();
|
||||
for (String key : mUiCreateEntries.keySet()) {
|
||||
createEntries.add(mUiCreateEntries.get(key).second);
|
||||
}
|
||||
return createEntries;
|
||||
}
|
||||
|
||||
private Entry prepareRemoteEntry() {
|
||||
if (mUiRemoteEntry == null || mUiRemoteEntry.first == null
|
||||
|| mUiRemoteEntry.second == null) {
|
||||
return null;
|
||||
}
|
||||
return mUiRemoteEntry.second.second;
|
||||
}
|
||||
|
||||
private boolean isEmptyResponse() {
|
||||
return mUiCreateEntries.isEmpty() && mUiRemoteEntry == null;
|
||||
}
|
||||
@Nullable
|
||||
public CreateEntry getRemoteEntry(String entryKey) {
|
||||
return mUiRemoteEntry == null || mUiRemoteEntry
|
||||
.first == null || !mUiRemoteEntry.first.equals(entryKey)
|
||||
|| mUiRemoteEntry.second == null
|
||||
? null : mUiRemoteEntry.second.first;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CreateEntry getCreateEntry(String entryKey) {
|
||||
return mUiCreateEntries.get(entryKey) == null
|
||||
? null : mUiCreateEntries.get(entryKey).first;
|
||||
}
|
||||
|
||||
public boolean isEmptyResponse(BeginCreateCredentialResponse response) {
|
||||
return (response.getCreateEntries() == null || response.getCreateEntries().isEmpty())
|
||||
&& response.getRemoteCreateEntry() == null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server.credentials;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.credentials.CredentialOption;
|
||||
@@ -45,7 +46,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Central provider session that listens for provider callbacks, and maintains provider state.
|
||||
@@ -69,14 +70,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
|
||||
@NonNull
|
||||
private final Map<String, CredentialOption> mBeginGetOptionToCredentialOptionMap;
|
||||
@NonNull
|
||||
private final Map<String, CredentialEntry> mUiCredentialEntries = new HashMap<>();
|
||||
@NonNull
|
||||
private final Map<String, Action> mUiActionsEntries = new HashMap<>();
|
||||
@Nullable
|
||||
private final Map<String, Action> mUiAuthenticationEntries = new HashMap<>();
|
||||
|
||||
@Nullable protected Pair<String, CredentialEntry> mUiRemoteEntry;
|
||||
|
||||
/** The complete request to be used in the second round. */
|
||||
private final android.credentials.GetCredentialRequest mCompleteRequest;
|
||||
@@ -84,6 +78,8 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
|
||||
private GetCredentialException mProviderException;
|
||||
|
||||
private final ProviderResponseDataHandler mProviderResponseDataHandler;
|
||||
|
||||
/** Creates a new provider session to be used by the request session. */
|
||||
@Nullable public static ProviderGetSession createNewSession(
|
||||
Context context,
|
||||
@@ -109,7 +105,8 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
beginGetOptionToCredentialOptionMap),
|
||||
filteredRequest,
|
||||
getRequestSession.mClientAppInfo,
|
||||
beginGetOptionToCredentialOptionMap
|
||||
beginGetOptionToCredentialOptionMap,
|
||||
getRequestSession.mHybridService
|
||||
);
|
||||
}
|
||||
Log.i(TAG, "Unable to create provider session");
|
||||
@@ -137,7 +134,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected static android.credentials.GetCredentialRequest filterOptions(
|
||||
private static android.credentials.GetCredentialRequest filterOptions(
|
||||
List<String> providerCapabilities,
|
||||
android.credentials.GetCredentialRequest clientRequest
|
||||
) {
|
||||
@@ -169,19 +166,22 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
BeginGetCredentialRequest beginGetRequest,
|
||||
android.credentials.GetCredentialRequest completeGetRequest,
|
||||
CallingAppInfo callingAppInfo,
|
||||
Map<String, CredentialOption> beginGetOptionToCredentialOptionMap) {
|
||||
Map<String, CredentialOption> beginGetOptionToCredentialOptionMap,
|
||||
String hybridService) {
|
||||
super(context, info, beginGetRequest, callbacks, userId, remoteCredentialService);
|
||||
mCompleteRequest = completeGetRequest;
|
||||
mCallingAppInfo = callingAppInfo;
|
||||
setStatus(Status.PENDING);
|
||||
mBeginGetOptionToCredentialOptionMap = new HashMap<>(beginGetOptionToCredentialOptionMap);
|
||||
mProviderResponseDataHandler = new ProviderResponseDataHandler(
|
||||
ComponentName.unflattenFromString(hybridService));
|
||||
}
|
||||
|
||||
/** Called when the provider response has been updated by an external source. */
|
||||
@Override // Callback from the remote provider
|
||||
public void onProviderResponseSuccess(@Nullable BeginGetCredentialResponse response) {
|
||||
Log.i(TAG, "in onProviderResponseSuccess");
|
||||
onUpdateResponse(response);
|
||||
onSetInitialRemoteResponse(response);
|
||||
}
|
||||
|
||||
/** Called when the provider response resulted in a failure. */
|
||||
@@ -207,18 +207,20 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
@Override // Selection call from the request provider
|
||||
protected void onUiEntrySelected(String entryType, String entryKey,
|
||||
ProviderPendingIntentResponse providerPendingIntentResponse) {
|
||||
Log.i(TAG, "onUiEntrySelected with entryKey: " + entryKey);
|
||||
switch (entryType) {
|
||||
case CREDENTIAL_ENTRY_KEY:
|
||||
CredentialEntry credentialEntry = mUiCredentialEntries.get(entryKey);
|
||||
CredentialEntry credentialEntry = mProviderResponseDataHandler
|
||||
.getCredentialEntry(entryKey);
|
||||
if (credentialEntry == null) {
|
||||
Log.i(TAG, "Unexpected credential entry key");
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
return;
|
||||
}
|
||||
onCredentialEntrySelected(credentialEntry, providerPendingIntentResponse);
|
||||
onCredentialEntrySelected(providerPendingIntentResponse);
|
||||
break;
|
||||
case ACTION_ENTRY_KEY:
|
||||
Action actionEntry = mUiActionsEntries.get(entryKey);
|
||||
Action actionEntry = mProviderResponseDataHandler.getActionEntry(entryKey);
|
||||
if (actionEntry == null) {
|
||||
Log.i(TAG, "Unexpected action entry key");
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
@@ -227,16 +229,29 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
onActionEntrySelected(providerPendingIntentResponse);
|
||||
break;
|
||||
case AUTHENTICATION_ACTION_ENTRY_KEY:
|
||||
Action authenticationEntry = mUiAuthenticationEntries.get(entryKey);
|
||||
Action authenticationEntry = mProviderResponseDataHandler
|
||||
.getAuthenticationAction(entryKey);
|
||||
if (authenticationEntry == null) {
|
||||
Log.i(TAG, "Unexpected authenticationEntry key");
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
return;
|
||||
}
|
||||
onAuthenticationEntrySelected(providerPendingIntentResponse);
|
||||
boolean additionalContentReceived =
|
||||
onAuthenticationEntrySelected(providerPendingIntentResponse);
|
||||
if (additionalContentReceived) {
|
||||
Log.i(TAG, "Additional content received - removing authentication entry");
|
||||
mProviderResponseDataHandler.removeAuthenticationAction(entryKey);
|
||||
} else {
|
||||
Log.i(TAG, "Additional content not received");
|
||||
mProviderResponseDataHandler
|
||||
.updateAuthEntryWithNoCredentialsReceived(entryKey);
|
||||
}
|
||||
if (!mProviderResponseDataHandler.isEmptyResponse()) {
|
||||
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
|
||||
}
|
||||
break;
|
||||
case REMOTE_ENTRY_KEY:
|
||||
if (mUiRemoteEntry.first.equals(entryKey)) {
|
||||
if (mProviderResponseDataHandler.getRemoteEntry(entryKey) != null) {
|
||||
onRemoteEntrySelected(providerPendingIntentResponse);
|
||||
} else {
|
||||
Log.i(TAG, "Unexpected remote entry key");
|
||||
@@ -245,6 +260,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
break;
|
||||
default:
|
||||
Log.i(TAG, "Unsupported entry type selected");
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,61 +280,11 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
+ mComponentName.flattenToString());
|
||||
return null;
|
||||
}
|
||||
if (mProviderResponse == null) {
|
||||
Log.i(TAG, "In prepareUiData response null");
|
||||
throw new IllegalStateException("Response must be in completion mode");
|
||||
if (mProviderResponse != null && !mProviderResponseDataHandler.isEmptyResponse()) {
|
||||
return mProviderResponseDataHandler.toGetCredentialProviderData();
|
||||
}
|
||||
return prepareUiProviderData(prepareUiActionEntries(
|
||||
mProviderResponse.getActions()),
|
||||
prepareUiCredentialEntries(mProviderResponse.getCredentialEntries()),
|
||||
prepareUiAuthenticationEntries(mProviderResponse.getAuthenticationActions()),
|
||||
prepareUiRemoteEntry(mProviderResponse.getRemoteCredentialEntry()));
|
||||
}
|
||||
|
||||
private Entry prepareUiRemoteEntry(CredentialEntry remoteCredentialEntry) {
|
||||
if (remoteCredentialEntry == null) {
|
||||
return null;
|
||||
}
|
||||
String entryId = generateUniqueId();
|
||||
Entry remoteEntry = new Entry(REMOTE_ENTRY_KEY, entryId, remoteCredentialEntry.getSlice(),
|
||||
setUpFillInIntent(remoteCredentialEntry.getType()));
|
||||
mUiRemoteEntry = new Pair<>(entryId, remoteCredentialEntry);
|
||||
return remoteEntry;
|
||||
}
|
||||
|
||||
private List<AuthenticationEntry> prepareUiAuthenticationEntries(
|
||||
@NonNull List<Action> authenticationEntries) {
|
||||
List<AuthenticationEntry> authenticationUiEntries = new ArrayList<>();
|
||||
|
||||
// TODO: properly construct entries when they should have the unlocked status.
|
||||
for (Action authenticationAction : authenticationEntries) {
|
||||
String entryId = generateUniqueId();
|
||||
mUiAuthenticationEntries.put(entryId, authenticationAction);
|
||||
authenticationUiEntries.add(new AuthenticationEntry(
|
||||
AUTHENTICATION_ACTION_ENTRY_KEY, entryId,
|
||||
authenticationAction.getSlice(),
|
||||
AuthenticationEntry.STATUS_LOCKED,
|
||||
setUpFillInIntentForAuthentication()));
|
||||
}
|
||||
return authenticationUiEntries;
|
||||
}
|
||||
|
||||
private List<Entry> prepareUiCredentialEntries(@NonNull
|
||||
List<CredentialEntry> credentialEntries) {
|
||||
Log.i(TAG, "in prepareUiProviderDataWithCredentials");
|
||||
List<Entry> credentialUiEntries = new ArrayList<>();
|
||||
|
||||
// Populate the credential entries
|
||||
for (CredentialEntry credentialEntry : credentialEntries) {
|
||||
String entryId = generateUniqueId();
|
||||
mUiCredentialEntries.put(entryId, credentialEntry);
|
||||
Log.i(TAG, "in prepareUiProviderData creating ui entry with id " + entryId);
|
||||
credentialUiEntries.add(new Entry(CREDENTIAL_ENTRY_KEY, entryId,
|
||||
credentialEntry.getSlice(),
|
||||
/*fillInIntent=*/setUpFillInIntent(credentialEntry
|
||||
.getBeginGetCredentialOption().getId())));
|
||||
}
|
||||
return credentialUiEntries;
|
||||
Log.i(TAG, "In prepareUiData response null");
|
||||
return null;
|
||||
}
|
||||
|
||||
private Intent setUpFillInIntent(@NonNull String id) {
|
||||
@@ -335,68 +301,47 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
mCallingAppInfo, mBeginGetOptionToCredentialOptionMap.get(id)));
|
||||
}
|
||||
|
||||
private Intent setUpFillInIntentForAuthentication() {
|
||||
private Intent setUpFillInIntentWithQueryRequest() {
|
||||
Intent intent = new Intent();
|
||||
intent.putExtra(
|
||||
CredentialProviderService
|
||||
.EXTRA_BEGIN_GET_CREDENTIAL_REQUEST,
|
||||
intent.putExtra(CredentialProviderService.EXTRA_BEGIN_GET_CREDENTIAL_REQUEST,
|
||||
mProviderRequest);
|
||||
return intent;
|
||||
}
|
||||
|
||||
private List<Entry> prepareUiActionEntries(@Nullable List<Action> actions) {
|
||||
List<Entry> actionEntries = new ArrayList<>();
|
||||
for (Action action : actions) {
|
||||
String entryId = UUID.randomUUID().toString();
|
||||
mUiActionsEntries.put(entryId, action);
|
||||
// TODO : Remove conversion of string to int after change in Entry class
|
||||
actionEntries.add(new Entry(ACTION_ENTRY_KEY, entryId, action.getSlice()));
|
||||
}
|
||||
return actionEntries;
|
||||
}
|
||||
|
||||
private GetCredentialProviderData prepareUiProviderData(List<Entry> actionEntries,
|
||||
List<Entry> credentialEntries, List<AuthenticationEntry> authenticationActionEntries,
|
||||
Entry remoteEntry) {
|
||||
return new GetCredentialProviderData.Builder(
|
||||
mComponentName.flattenToString()).setActionChips(actionEntries)
|
||||
.setCredentialEntries(credentialEntries)
|
||||
.setAuthenticationEntries(authenticationActionEntries)
|
||||
.setRemoteEntry(remoteEntry)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void onCredentialEntrySelected(CredentialEntry credentialEntry,
|
||||
private void onRemoteEntrySelected(
|
||||
ProviderPendingIntentResponse providerPendingIntentResponse) {
|
||||
if (providerPendingIntentResponse != null) {
|
||||
// Check if pending intent has an error
|
||||
GetCredentialException exception = maybeGetPendingIntentException(
|
||||
providerPendingIntentResponse);
|
||||
if (exception != null) {
|
||||
invokeCallbackWithError(exception.getType(),
|
||||
exception.getMessage());
|
||||
return;
|
||||
}
|
||||
onCredentialEntrySelected(providerPendingIntentResponse);
|
||||
}
|
||||
|
||||
// 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");
|
||||
private void onCredentialEntrySelected(
|
||||
ProviderPendingIntentResponse providerPendingIntentResponse) {
|
||||
if (providerPendingIntentResponse == null) {
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
return;
|
||||
}
|
||||
Log.i(TAG, "CredentialEntry does not have a credential or a pending intent result");
|
||||
// Check if pending intent has an error
|
||||
GetCredentialException exception = maybeGetPendingIntentException(
|
||||
providerPendingIntentResponse);
|
||||
if (exception != null) {
|
||||
invokeCallbackWithError(exception.getType(), exception.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if pending intent has a credential response
|
||||
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");
|
||||
invokeCallbackOnInternalInvalidState();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected GetCredentialException maybeGetPendingIntentException(
|
||||
private GetCredentialException maybeGetPendingIntentException(
|
||||
ProviderPendingIntentResponse pendingIntentResponse) {
|
||||
if (pendingIntentResponse == null) {
|
||||
Log.i(TAG, "pendingIntentResponse is null");
|
||||
@@ -417,13 +362,19 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
return null;
|
||||
}
|
||||
|
||||
private void onAuthenticationEntrySelected(
|
||||
/**
|
||||
* Returns true if either an exception or a response is retrieved from the result.
|
||||
* Returns false if the response is not set at all, or set to null, or empty.
|
||||
*/
|
||||
private boolean onAuthenticationEntrySelected(
|
||||
@Nullable ProviderPendingIntentResponse providerPendingIntentResponse) {
|
||||
//TODO: Other provider intent statuses
|
||||
Log.i(TAG, "onAuthenticationEntrySelected");
|
||||
// Authentication entry is expected to have a BeginGetCredentialResponse instance. If it
|
||||
// does not have it, we remove the authentication entry and do not add any more content.
|
||||
if (providerPendingIntentResponse == null) {
|
||||
Log.i(TAG, "providerPendingIntentResponse is null");
|
||||
onUpdateEmptyResponse();
|
||||
return;
|
||||
// Nothing received. This is equivalent to no content received.
|
||||
return false;
|
||||
}
|
||||
|
||||
GetCredentialException exception = maybeGetPendingIntentException(
|
||||
@@ -431,51 +382,69 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
if (exception != null) {
|
||||
invokeCallbackWithError(exception.getType(),
|
||||
exception.getMessage());
|
||||
return;
|
||||
// Additional content received is in the form of an exception which ends the flow.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check if pending intent has the content
|
||||
BeginGetCredentialResponse content = PendingIntentResultHandler
|
||||
// Check if pending intent has the response. If yes, remove this auth entry and
|
||||
// replace it with the response content received.
|
||||
BeginGetCredentialResponse response = PendingIntentResultHandler
|
||||
.extractResponseContent(providerPendingIntentResponse
|
||||
.getResultData());
|
||||
if (content != null) {
|
||||
onUpdateResponse(content);
|
||||
if (response != null && !mProviderResponseDataHandler.isEmptyResponse(response)) {
|
||||
addToInitialRemoteResponse(response);
|
||||
// Additional content received is in the form of new response content.
|
||||
return true;
|
||||
}
|
||||
// No response or exception found.
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addToInitialRemoteResponse(BeginGetCredentialResponse content) {
|
||||
if (content == null) {
|
||||
return;
|
||||
}
|
||||
mProviderResponseDataHandler.addResponseContent(
|
||||
content.getCredentialEntries(),
|
||||
content.getActions(),
|
||||
content.getAuthenticationActions(),
|
||||
content.getRemoteCredentialEntry()
|
||||
);
|
||||
}
|
||||
|
||||
/** Returns true if either an exception or a response is found. */
|
||||
private void onActionEntrySelected(ProviderPendingIntentResponse
|
||||
providerPendingIntentResponse) {
|
||||
// Action entry is expected to either contain the final GetCredentialResponse, or it is
|
||||
// also acceptable if it does not contain anything. In the second case, we re-show this
|
||||
// action on the UI.
|
||||
if (providerPendingIntentResponse == null) {
|
||||
Log.i(TAG, "providerPendingIntentResponse is null");
|
||||
return;
|
||||
}
|
||||
|
||||
Log.i(TAG, "No error or respond found in pending intent response");
|
||||
onUpdateEmptyResponse();
|
||||
}
|
||||
|
||||
private void onActionEntrySelected(ProviderPendingIntentResponse
|
||||
providerPendingIntentResponse) {
|
||||
//TODO: Implement if any result expected after an action
|
||||
GetCredentialException exception = maybeGetPendingIntentException(
|
||||
providerPendingIntentResponse);
|
||||
if (exception != null) {
|
||||
invokeCallbackWithError(exception.getType(), exception.getMessage());
|
||||
}
|
||||
GetCredentialResponse response = PendingIntentResultHandler
|
||||
.extractGetCredentialResponse(
|
||||
providerPendingIntentResponse.getResultData());
|
||||
if (response != null) {
|
||||
mCallbacks.onFinalResponseReceived(mComponentName, response);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Updates the response being maintained in state by this provider session. */
|
||||
private void onUpdateResponse(BeginGetCredentialResponse response) {
|
||||
private void onSetInitialRemoteResponse(BeginGetCredentialResponse response) {
|
||||
mProviderResponse = response;
|
||||
if (isEmptyResponse(response)) {
|
||||
addToInitialRemoteResponse(response);
|
||||
if (mProviderResponseDataHandler.isEmptyResponse(response)) {
|
||||
updateStatusAndInvokeCallback(Status.EMPTY_RESPONSE);
|
||||
} else {
|
||||
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isEmptyResponse(BeginGetCredentialResponse response) {
|
||||
if ((response.getCredentialEntries() == null || response.getCredentialEntries().isEmpty())
|
||||
&& (response.getAuthenticationActions() == null || response
|
||||
.getAuthenticationActions().isEmpty())
|
||||
&& (response.getActions() == null || response.getActions().isEmpty())
|
||||
&& response.getRemoteCredentialEntry() == null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void onUpdateEmptyResponse() {
|
||||
updateStatusAndInvokeCallback(Status.NO_CREDENTIALS);
|
||||
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -486,4 +455,201 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
mCallbacks.onFinalErrorReceived(mComponentName,
|
||||
GetCredentialException.TYPE_UNKNOWN, null);
|
||||
}
|
||||
|
||||
private class ProviderResponseDataHandler {
|
||||
private final ComponentName mExpectedRemoteEntryProviderService;
|
||||
@NonNull
|
||||
private final Map<String, Pair<CredentialEntry, Entry>> mUiCredentialEntries =
|
||||
new HashMap<>();
|
||||
@NonNull
|
||||
private final Map<String, Pair<Action, Entry>> mUiActionsEntries = new HashMap<>();
|
||||
@Nullable
|
||||
private final Map<String, Pair<Action, AuthenticationEntry>> mUiAuthenticationEntries =
|
||||
new HashMap<>();
|
||||
|
||||
@Nullable private Pair<String, Pair<CredentialEntry, Entry>> mUiRemoteEntry = null;
|
||||
|
||||
ProviderResponseDataHandler(ComponentName expectedRemoteEntryProviderService) {
|
||||
mExpectedRemoteEntryProviderService = expectedRemoteEntryProviderService;
|
||||
}
|
||||
|
||||
public void addResponseContent(List<CredentialEntry> credentialEntries,
|
||||
List<Action> actions, List<Action> authenticationActions,
|
||||
CredentialEntry remoteEntry) {
|
||||
credentialEntries.forEach(this::addCredentialEntry);
|
||||
actions.forEach(this::addAction);
|
||||
authenticationActions.forEach(
|
||||
authenticationAction -> addAuthenticationAction(authenticationAction,
|
||||
AuthenticationEntry.STATUS_LOCKED));
|
||||
setRemoteEntry(remoteEntry);
|
||||
}
|
||||
public void addCredentialEntry(CredentialEntry credentialEntry) {
|
||||
String id = generateUniqueId();
|
||||
Entry entry = new Entry(CREDENTIAL_ENTRY_KEY,
|
||||
id, credentialEntry.getSlice(),
|
||||
setUpFillInIntent(credentialEntry
|
||||
.getBeginGetCredentialOption().getId()));
|
||||
mUiCredentialEntries.put(id, new Pair<>(credentialEntry, entry));
|
||||
}
|
||||
|
||||
public void addAction(Action action) {
|
||||
String id = generateUniqueId();
|
||||
Entry entry = new Entry(ACTION_ENTRY_KEY,
|
||||
id, action.getSlice(),
|
||||
setUpFillInIntentWithQueryRequest());
|
||||
mUiActionsEntries.put(id, new Pair<>(action, entry));
|
||||
}
|
||||
|
||||
public void addAuthenticationAction(Action authenticationAction,
|
||||
@AuthenticationEntry.Status int status) {
|
||||
Log.i(TAG, "In addAuthenticationAction");
|
||||
String id = generateUniqueId();
|
||||
Log.i(TAG, "In addAuthenticationAction, id : " + id);
|
||||
AuthenticationEntry entry = new AuthenticationEntry(
|
||||
AUTHENTICATION_ACTION_ENTRY_KEY,
|
||||
id, authenticationAction.getSlice(),
|
||||
status,
|
||||
setUpFillInIntentWithQueryRequest());
|
||||
mUiAuthenticationEntries.put(id, new Pair<>(authenticationAction, entry));
|
||||
}
|
||||
|
||||
public void removeAuthenticationAction(String id) {
|
||||
mUiAuthenticationEntries.remove(id);
|
||||
}
|
||||
|
||||
public void setRemoteEntry(@Nullable CredentialEntry remoteEntry) {
|
||||
if (remoteEntry == null) {
|
||||
return;
|
||||
}
|
||||
if (!mComponentName.equals(mExpectedRemoteEntryProviderService)) {
|
||||
Log.i(TAG, "Remote entry being dropped as it is not from the service "
|
||||
+ "configured by the OEM.");
|
||||
return;
|
||||
}
|
||||
String id = generateUniqueId();
|
||||
Entry entry = new Entry(REMOTE_ENTRY_KEY,
|
||||
id, remoteEntry.getSlice(), setUpFillInIntent(
|
||||
remoteEntry.getBeginGetCredentialOption().getId()));
|
||||
mUiRemoteEntry = new Pair<>(generateUniqueId(), new Pair<>(remoteEntry, entry));
|
||||
}
|
||||
|
||||
public GetCredentialProviderData toGetCredentialProviderData() {
|
||||
return new GetCredentialProviderData.Builder(
|
||||
mComponentName.flattenToString()).setActionChips(prepareActionEntries())
|
||||
.setCredentialEntries(prepareCredentialEntries())
|
||||
.setAuthenticationEntries(prepareAuthenticationEntries())
|
||||
.setRemoteEntry(prepareRemoteEntry())
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<Entry> prepareActionEntries() {
|
||||
List<Entry> actionEntries = new ArrayList<>();
|
||||
for (String key : mUiActionsEntries.keySet()) {
|
||||
actionEntries.add(mUiActionsEntries.get(key).second);
|
||||
}
|
||||
return actionEntries;
|
||||
}
|
||||
|
||||
private List<AuthenticationEntry> prepareAuthenticationEntries() {
|
||||
List<AuthenticationEntry> authEntries = new ArrayList<>();
|
||||
for (String key : mUiAuthenticationEntries.keySet()) {
|
||||
authEntries.add(mUiAuthenticationEntries.get(key).second);
|
||||
}
|
||||
return authEntries;
|
||||
}
|
||||
|
||||
private List<Entry> prepareCredentialEntries() {
|
||||
List<Entry> credEntries = new ArrayList<>();
|
||||
for (String key : mUiCredentialEntries.keySet()) {
|
||||
credEntries.add(mUiCredentialEntries.get(key).second);
|
||||
}
|
||||
return credEntries;
|
||||
}
|
||||
|
||||
|
||||
private Entry prepareRemoteEntry() {
|
||||
if (mUiRemoteEntry == null || mUiRemoteEntry.first == null
|
||||
|| mUiRemoteEntry.second == null) {
|
||||
return null;
|
||||
}
|
||||
return mUiRemoteEntry.second.second;
|
||||
}
|
||||
|
||||
private boolean isEmptyResponse() {
|
||||
return mUiCredentialEntries.isEmpty() && mUiActionsEntries.isEmpty()
|
||||
&& mUiAuthenticationEntries.isEmpty() && mUiRemoteEntry == null;
|
||||
}
|
||||
|
||||
private boolean isEmptyResponse(BeginGetCredentialResponse response) {
|
||||
return response.getCredentialEntries().isEmpty() && response.getActions().isEmpty()
|
||||
&& response.getAuthenticationActions().isEmpty()
|
||||
&& response.getRemoteCredentialEntry() == null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Action getAuthenticationAction(String entryKey) {
|
||||
return mUiAuthenticationEntries.get(entryKey) == null ? null :
|
||||
mUiAuthenticationEntries.get(entryKey).first;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Action getActionEntry(String entryKey) {
|
||||
return mUiActionsEntries.get(entryKey) == null
|
||||
? null : mUiActionsEntries.get(entryKey).first;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CredentialEntry getRemoteEntry(String entryKey) {
|
||||
return mUiRemoteEntry.first.equals(entryKey) && mUiRemoteEntry.second != null
|
||||
? mUiRemoteEntry.second.first : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public CredentialEntry getCredentialEntry(String entryKey) {
|
||||
return mUiCredentialEntries.get(entryKey) == null
|
||||
? null : mUiCredentialEntries.get(entryKey).first;
|
||||
}
|
||||
|
||||
public void updateAuthEntryWithNoCredentialsReceived(String entryKey) {
|
||||
updatePreviousMostRecentAuthEntry();
|
||||
updateMostRecentAuthEntry(entryKey);
|
||||
}
|
||||
|
||||
private void updateMostRecentAuthEntry(String entryKey) {
|
||||
AuthenticationEntry previousAuthenticationEntry =
|
||||
mUiAuthenticationEntries.get(entryKey).second;
|
||||
Action previousAuthenticationAction = mUiAuthenticationEntries.get(entryKey).first;
|
||||
mUiAuthenticationEntries.put(entryKey, new Pair<>(
|
||||
previousAuthenticationAction,
|
||||
copyAuthEntryAndChangeStatus(
|
||||
previousAuthenticationEntry,
|
||||
AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT)));
|
||||
}
|
||||
|
||||
private void updatePreviousMostRecentAuthEntry() {
|
||||
Optional<Map.Entry<String, Pair<Action, AuthenticationEntry>>>
|
||||
previousMostRecentAuthEntry = mUiAuthenticationEntries
|
||||
.entrySet().stream().filter(e -> e.getValue().second.getStatus()
|
||||
== AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_MOST_RECENT)
|
||||
.findFirst();
|
||||
if (previousMostRecentAuthEntry.isEmpty()) {
|
||||
Log.i(TAG, "In updatePreviousMostRecentAuthEntry - previous entry not found");
|
||||
return;
|
||||
}
|
||||
String id = previousMostRecentAuthEntry.get().getKey();
|
||||
mUiAuthenticationEntries.remove(id);
|
||||
mUiAuthenticationEntries.put(id, new Pair<>(
|
||||
previousMostRecentAuthEntry.get().getValue().first,
|
||||
copyAuthEntryAndChangeStatus(
|
||||
previousMostRecentAuthEntry.get().getValue().second,
|
||||
AuthenticationEntry.STATUS_UNLOCKED_BUT_EMPTY_LESS_RECENT)));
|
||||
}
|
||||
|
||||
private AuthenticationEntry copyAuthEntryAndChangeStatus(
|
||||
AuthenticationEntry from, Integer toStatus) {
|
||||
return new AuthenticationEntry(AUTHENTICATION_ACTION_ENTRY_KEY, from.getSubkey(),
|
||||
from.getSlice(), toStatus,
|
||||
from.getFrameworkExtrasIntent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,8 +66,7 @@ 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
|
||||
|| status == Status.REQUIRES_AUTHENTICATION;
|
||||
return status == Status.CREDENTIALS_RECEIVED || status == Status.SAVE_ENTRIES_RECEIVED;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,11 +207,6 @@ public abstract class ProviderSession<T, R>
|
||||
}
|
||||
}
|
||||
|
||||
protected void onRemoteEntrySelected(
|
||||
ProviderPendingIntentResponse providerPendingIntentResponse) {
|
||||
//TODO: Implement
|
||||
}
|
||||
|
||||
/** Get the request to be sent to the provider. */
|
||||
protected T getProviderRequest() {
|
||||
return mProviderRequest;
|
||||
|
||||
@@ -38,6 +38,7 @@ import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.util.FrameworkStatsLog;
|
||||
import com.android.server.credentials.metrics.CandidateProviderMetric;
|
||||
import com.android.server.credentials.metrics.ChosenProviderMetric;
|
||||
@@ -79,6 +80,7 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
|
||||
protected final Map<String, ProviderSession> mProviders = new HashMap<>();
|
||||
protected ChosenProviderMetric mChosenProviderMetric = new ChosenProviderMetric();
|
||||
//TODO improve design to allow grouped metrics per request
|
||||
protected final String mHybridService;
|
||||
|
||||
protected RequestSession(@NonNull Context context,
|
||||
@UserIdInt int userId, int callingUid, @NonNull T clientRequest, U clientCallback,
|
||||
@@ -97,6 +99,8 @@ abstract class RequestSession<T, U> implements CredentialManagerUi.CredentialMan
|
||||
mRequestId = new Binder();
|
||||
mCredentialManagerUi = new CredentialManagerUi(mContext,
|
||||
mUserId, this);
|
||||
mHybridService = context.getResources().getString(
|
||||
R.string.config_defaultCredentialManagerHybridService);
|
||||
}
|
||||
|
||||
public abstract ProviderSession initiateProviderSession(CredentialProviderInfo providerInfo,
|
||||
|
||||
Reference in New Issue
Block a user