script-astra/Android/Sdk/sources/android-35/android/credentials/PrepareGetCredentialResponse.java

189 lines
7.8 KiB
Java
Raw Permalink Normal View History

2025-01-20 15:15:20 +00:00
/*
* Copyright 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.credentials;
import static android.Manifest.permission.CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.app.ActivityOptions;
import android.app.PendingIntent;
import android.content.Context;
import android.content.IntentSender;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.OutcomeReceiver;
import android.util.Log;
import java.util.concurrent.Executor;
/**
* A response object that prefetches user app credentials and provides metadata about them. It can
* then be used to issue the full credential retrieval flow via the
* {@link CredentialManager#getCredential(Context, PendingGetCredentialHandle, CancellationSignal,
* Executor, OutcomeReceiver)} method to perform the remaining flows such as consent collection
* and credential selection, to officially retrieve a credential.
*/
public final class PrepareGetCredentialResponse {
private static final Bundle OPTIONS_SENDER_BAL_OPTIN = ActivityOptions.makeBasic()
.setPendingIntentBackgroundActivityStartMode(
ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED).toBundle();
/**
* A handle that represents a pending get-credential operation. Pass this handle to {@link
* CredentialManager#getCredential(Context, PendingGetCredentialHandle, CancellationSignal,
* Executor, OutcomeReceiver)} to perform the remaining flows to officially retrieve a
* credential.
*/
public static final class PendingGetCredentialHandle {
@NonNull
private final CredentialManager.GetCredentialTransportPendingUseCase
mGetCredentialTransport;
/**
* The pending intent to be launched to finalize the user credential. If null, the callback
* will fail with {@link GetCredentialException#TYPE_NO_CREDENTIAL}.
*/
@Nullable
private final PendingIntent mPendingIntent;
/** @hide */
PendingGetCredentialHandle(
@NonNull CredentialManager.GetCredentialTransportPendingUseCase transport,
@Nullable PendingIntent pendingIntent) {
mGetCredentialTransport = transport;
mPendingIntent = pendingIntent;
}
/** @hide */
void show(@NonNull Context context, @Nullable CancellationSignal cancellationSignal,
@CallbackExecutor @NonNull Executor executor,
@NonNull OutcomeReceiver<GetCredentialResponse, GetCredentialException> callback) {
if (mPendingIntent == null) {
executor.execute(() -> callback.onError(
new GetCredentialException(GetCredentialException.TYPE_NO_CREDENTIAL)));
return;
}
mGetCredentialTransport.setCallback(new GetPendingCredentialInternalCallback() {
@Override
public void onPendingIntent(PendingIntent pendingIntent) {
try {
context.startIntentSender(pendingIntent.getIntentSender(), null, 0, 0, 0,
OPTIONS_SENDER_BAL_OPTIN);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "startIntentSender() failed for intent for show()", e);
executor.execute(() -> callback.onError(
new GetCredentialException(GetCredentialException.TYPE_UNKNOWN)));
}
}
@Override
public void onResponse(GetCredentialResponse response) {
executor.execute(() -> callback.onResult(response));
}
@Override
public void onError(String errorType, String message) {
executor.execute(
() -> callback.onError(new GetCredentialException(errorType, message)));
}
});
try {
context.startIntentSender(mPendingIntent.getIntentSender(), null, 0, 0, 0,
OPTIONS_SENDER_BAL_OPTIN);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "startIntentSender() failed for intent for show()", e);
executor.execute(() -> callback.onError(
new GetCredentialException(GetCredentialException.TYPE_UNKNOWN)));
}
}
}
private static final String TAG = "CredentialManager";
@NonNull private final PrepareGetCredentialResponseInternal mResponseInternal;
@NonNull private final PendingGetCredentialHandle mPendingGetCredentialHandle;
/**
* Returns true if the user has any candidate credentials for the given {@code credentialType},
* and false otherwise.
*/
@RequiresPermission(CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS)
public boolean hasCredentialResults(@NonNull String credentialType) {
return mResponseInternal.hasCredentialResults(credentialType);
}
/**
* Returns true if the user has any candidate authentication actions (locked credential
* supplier), and false otherwise.
*/
@RequiresPermission(CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS)
public boolean hasAuthenticationResults() {
return mResponseInternal.hasAuthenticationResults();
}
/**
* Returns true if the user has any candidate remote credential results, and false otherwise.
*/
@RequiresPermission(CREDENTIAL_MANAGER_QUERY_CANDIDATE_CREDENTIALS)
public boolean hasRemoteResults() {
return mResponseInternal.hasRemoteResults();
}
/**
* Returns a handle that represents this pending get-credential operation. Pass this handle to
* {@link CredentialManager#getCredential(Context, PendingGetCredentialHandle,
* CancellationSignal, Executor, OutcomeReceiver)} to perform the remaining flows to officially
* retrieve a credential.
*/
@NonNull
public PendingGetCredentialHandle getPendingGetCredentialHandle() {
return mPendingGetCredentialHandle;
}
/**
* Constructs a {@link PrepareGetCredentialResponse}.
*
* @param responseInternal whether caller has the permission to query the credential
* result metadata
* @param getCredentialTransport the transport for the operation to finalaze a credential
* @hide
*/
protected PrepareGetCredentialResponse(
@NonNull PrepareGetCredentialResponseInternal responseInternal,
@NonNull CredentialManager.GetCredentialTransportPendingUseCase
getCredentialTransport) {
mResponseInternal = responseInternal;
mPendingGetCredentialHandle = new PendingGetCredentialHandle(
getCredentialTransport, responseInternal.getPendingIntent());
}
/** @hide */
protected interface GetPendingCredentialInternalCallback {
void onPendingIntent(@NonNull PendingIntent pendingIntent);
void onResponse(@NonNull GetCredentialResponse response);
void onError(@NonNull String errorType, @Nullable String message);
}
}