Merge "Fix cancellation on the provider side" into udc-dev
This commit is contained in:
@@ -231,12 +231,18 @@ public abstract class CredentialProviderService extends Service {
|
||||
}
|
||||
|
||||
private final ICredentialProviderService mInterface = new ICredentialProviderService.Stub() {
|
||||
public ICancellationSignal onBeginGetCredential(BeginGetCredentialRequest request,
|
||||
@Override
|
||||
public void onBeginGetCredential(BeginGetCredentialRequest request,
|
||||
IBeginGetCredentialCallback callback) {
|
||||
Objects.requireNonNull(request);
|
||||
Objects.requireNonNull(callback);
|
||||
|
||||
ICancellationSignal transport = CancellationSignal.createTransport();
|
||||
try {
|
||||
callback.onCancellable(transport);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
mHandler.sendMessage(obtainMessage(
|
||||
CredentialProviderService::onBeginGetCredential,
|
||||
@@ -267,7 +273,6 @@ public abstract class CredentialProviderService extends Service {
|
||||
}
|
||||
}
|
||||
));
|
||||
return transport;
|
||||
}
|
||||
private void enforceRemoteEntryPermission() {
|
||||
String permission =
|
||||
@@ -280,12 +285,17 @@ public abstract class CredentialProviderService extends Service {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICancellationSignal onBeginCreateCredential(BeginCreateCredentialRequest request,
|
||||
public void onBeginCreateCredential(BeginCreateCredentialRequest request,
|
||||
IBeginCreateCredentialCallback callback) {
|
||||
Objects.requireNonNull(request);
|
||||
Objects.requireNonNull(callback);
|
||||
|
||||
ICancellationSignal transport = CancellationSignal.createTransport();
|
||||
try {
|
||||
callback.onCancellable(transport);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
mHandler.sendMessage(obtainMessage(
|
||||
CredentialProviderService::onBeginCreateCredential,
|
||||
@@ -316,16 +326,20 @@ public abstract class CredentialProviderService extends Service {
|
||||
}
|
||||
}
|
||||
));
|
||||
return transport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICancellationSignal onClearCredentialState(ClearCredentialStateRequest request,
|
||||
public void onClearCredentialState(ClearCredentialStateRequest request,
|
||||
IClearCredentialStateCallback callback) {
|
||||
Objects.requireNonNull(request);
|
||||
Objects.requireNonNull(callback);
|
||||
|
||||
ICancellationSignal transport = CancellationSignal.createTransport();
|
||||
try {
|
||||
callback.onCancellable(transport);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
mHandler.sendMessage(obtainMessage(
|
||||
CredentialProviderService::onClearCredentialState,
|
||||
@@ -350,7 +364,6 @@ public abstract class CredentialProviderService extends Service {
|
||||
}
|
||||
}
|
||||
));
|
||||
return transport;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package android.service.credentials;
|
||||
|
||||
import android.service.credentials.BeginCreateCredentialResponse;
|
||||
import android.os.ICancellationSignal;
|
||||
|
||||
/**
|
||||
* Interface from the system to a credential provider service.
|
||||
@@ -10,4 +11,5 @@ import android.service.credentials.BeginCreateCredentialResponse;
|
||||
oneway interface IBeginCreateCredentialCallback {
|
||||
void onSuccess(in BeginCreateCredentialResponse request);
|
||||
void onFailure(String errorType, in CharSequence message);
|
||||
void onCancellable(in ICancellationSignal cancellation);
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package android.service.credentials;
|
||||
|
||||
import android.service.credentials.BeginGetCredentialResponse;
|
||||
import android.os.ICancellationSignal;
|
||||
|
||||
|
||||
/**
|
||||
* Interface from the system to a credential provider service.
|
||||
@@ -10,4 +12,5 @@ import android.service.credentials.BeginGetCredentialResponse;
|
||||
oneway interface IBeginGetCredentialCallback {
|
||||
void onSuccess(in BeginGetCredentialResponse response);
|
||||
void onFailure(String errorType, in CharSequence message);
|
||||
void onCancellable(in ICancellationSignal cancellation);
|
||||
}
|
||||
@@ -16,12 +16,16 @@
|
||||
|
||||
package android.service.credentials;
|
||||
|
||||
import android.os.ICancellationSignal;
|
||||
|
||||
|
||||
/**
|
||||
* Callback for onClearCredentialState request.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface IClearCredentialStateCallback {
|
||||
oneway void onSuccess();
|
||||
oneway void onFailure(String errorType, CharSequence message);
|
||||
oneway interface IClearCredentialStateCallback {
|
||||
void onSuccess();
|
||||
void onFailure(String errorType, CharSequence message);
|
||||
void onCancellable(in ICancellationSignal cancellation);
|
||||
}
|
||||
@@ -30,8 +30,8 @@ import android.os.ICancellationSignal;
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface ICredentialProviderService {
|
||||
ICancellationSignal onBeginGetCredential(in BeginGetCredentialRequest request, in IBeginGetCredentialCallback callback);
|
||||
ICancellationSignal onBeginCreateCredential(in BeginCreateCredentialRequest request, in IBeginCreateCredentialCallback callback);
|
||||
ICancellationSignal onClearCredentialState(in ClearCredentialStateRequest request, in IClearCredentialStateCallback callback);
|
||||
oneway interface ICredentialProviderService {
|
||||
void onBeginGetCredential(in BeginGetCredentialRequest request, in IBeginGetCredentialCallback callback);
|
||||
void onBeginCreateCredential(in BeginCreateCredentialRequest request, in IBeginCreateCredentialCallback callback);
|
||||
void onClearCredentialState(in ClearCredentialStateRequest request, in IClearCredentialStateCallback callback);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.credentials.ClearCredentialStateException;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.ClearCredentialStateRequest;
|
||||
import android.util.Log;
|
||||
@@ -109,6 +110,11 @@ public final class ProviderClearSession extends ProviderSession<ClearCredentialS
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderCancellable(ICancellationSignal cancellation) {
|
||||
mProviderCancellationSignal = cancellation;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected ProviderData prepareUiData() {
|
||||
@@ -126,8 +132,7 @@ public final class ProviderClearSession extends ProviderSession<ClearCredentialS
|
||||
protected void invokeSession() {
|
||||
if (mRemoteCredentialService != null) {
|
||||
startCandidateMetrics();
|
||||
mProviderCancellationSignal =
|
||||
mRemoteCredentialService.onClearCredentialState(mProviderRequest, this);
|
||||
mRemoteCredentialService.onClearCredentialState(mProviderRequest, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.credentials.ui.CreateCredentialProviderData;
|
||||
import android.credentials.ui.Entry;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.os.Bundle;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.service.credentials.BeginCreateCredentialRequest;
|
||||
import android.service.credentials.BeginCreateCredentialResponse;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
@@ -173,6 +174,11 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderCancellable(ICancellationSignal cancellation) {
|
||||
mProviderCancellationSignal = cancellation;
|
||||
}
|
||||
|
||||
private void onSetInitialRemoteResponse(BeginCreateCredentialResponse response) {
|
||||
Log.i(TAG, "onSetInitialRemoteResponse with save entries");
|
||||
mProviderResponse = response;
|
||||
@@ -236,8 +242,7 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
protected void invokeSession() {
|
||||
if (mRemoteCredentialService != null) {
|
||||
startCandidateMetrics();
|
||||
mProviderCancellationSignal =
|
||||
mRemoteCredentialService.onCreateCredential(mProviderRequest, this);
|
||||
mRemoteCredentialService.onBeginCreateCredential(mProviderRequest, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.credentials.ui.AuthenticationEntry;
|
||||
import android.credentials.ui.Entry;
|
||||
import android.credentials.ui.GetCredentialProviderData;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.service.credentials.Action;
|
||||
import android.service.credentials.BeginGetCredentialOption;
|
||||
import android.service.credentials.BeginGetCredentialRequest;
|
||||
@@ -235,6 +236,11 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderCancellable(ICancellationSignal cancellation) {
|
||||
mProviderCancellationSignal = cancellation;
|
||||
}
|
||||
|
||||
@Override // Selection call from the request provider
|
||||
protected void onUiEntrySelected(String entryType, String entryKey,
|
||||
ProviderPendingIntentResponse providerPendingIntentResponse) {
|
||||
@@ -302,9 +308,7 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
protected void invokeSession() {
|
||||
if (mRemoteCredentialService != null) {
|
||||
startCandidateMetrics();
|
||||
mProviderCancellationSignal =
|
||||
mRemoteCredentialService.onBeginGetCredential(mProviderRequest, this);
|
||||
boolean foundSig = mProviderCancellationSignal == null;
|
||||
mRemoteCredentialService.onBeginGetCredential(mProviderRequest, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.credentials.ui.Entry;
|
||||
import android.credentials.ui.GetCredentialProviderData;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CredentialEntry;
|
||||
import android.service.credentials.CredentialProviderService;
|
||||
@@ -115,7 +116,7 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption
|
||||
@NonNull String servicePackageName,
|
||||
@NonNull CredentialOption requestOption) {
|
||||
super(context, requestOption, session,
|
||||
new ComponentName(servicePackageName, servicePackageName) ,
|
||||
new ComponentName(servicePackageName, servicePackageName),
|
||||
userId, null);
|
||||
mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId);
|
||||
mCallingAppInfo = callingAppInfo;
|
||||
@@ -132,7 +133,7 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption
|
||||
@NonNull String servicePackageName,
|
||||
@NonNull CredentialOption requestOption) {
|
||||
super(context, requestOption, session,
|
||||
new ComponentName(servicePackageName, servicePackageName) ,
|
||||
new ComponentName(servicePackageName, servicePackageName),
|
||||
userId, null);
|
||||
mCredentialDescriptionRegistry = CredentialDescriptionRegistry.forUser(userId);
|
||||
mCallingAppInfo = callingAppInfo;
|
||||
@@ -254,14 +255,19 @@ public class ProviderRegistryGetSession extends ProviderSession<CredentialOption
|
||||
// No need to do anything since this class does not rely on a remote service.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProviderCancellable(ICancellationSignal cancellation) {
|
||||
// No need to do anything since this class does not rely on a remote service.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void invokeSession() {
|
||||
mProviderResponse = mCredentialDescriptionRegistry
|
||||
.getFilteredResultForProvider(mCredentialProviderPackageName,
|
||||
mElementKeys);
|
||||
mCredentialEntries = mProviderResponse.stream().flatMap(
|
||||
(Function<CredentialDescriptionRegistry.FilterResult,
|
||||
Stream<CredentialEntry>>) filterResult
|
||||
(Function<CredentialDescriptionRegistry.FilterResult,
|
||||
Stream<CredentialEntry>>) filterResult
|
||||
-> filterResult.mCredentialEntries.stream())
|
||||
.collect(Collectors.toList());
|
||||
updateStatusAndInvokeCallback(Status.CREDENTIALS_RECEIVED,
|
||||
|
||||
@@ -82,6 +82,9 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
|
||||
/** Called when the remote provider service dies. */
|
||||
void onProviderServiceDied(RemoteCredentialService service);
|
||||
|
||||
/** Called to set the cancellation transport from the remote provider service. */
|
||||
void onProviderCancellable(ICancellationSignal cancellation);
|
||||
}
|
||||
|
||||
public RemoteCredentialService(@NonNull Context context,
|
||||
@@ -117,43 +120,56 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
* @param callback the callback to be used to send back the provider response to the
|
||||
* {@link ProviderGetSession} class that maintains provider state
|
||||
*/
|
||||
public ICancellationSignal onBeginGetCredential(@NonNull BeginGetCredentialRequest request,
|
||||
public void onBeginGetCredential(@NonNull BeginGetCredentialRequest request,
|
||||
ProviderCallbacks<BeginGetCredentialResponse> callback) {
|
||||
Log.i(TAG, "In onGetCredentials in RemoteCredentialService");
|
||||
AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
|
||||
AtomicReference<CompletableFuture<BeginGetCredentialResponse>> futureRef =
|
||||
new AtomicReference<>();
|
||||
|
||||
|
||||
CompletableFuture<BeginGetCredentialResponse> connectThenExecute = postAsync(service -> {
|
||||
CompletableFuture<BeginGetCredentialResponse> getCredentials =
|
||||
new CompletableFuture<>();
|
||||
final long originalCallingUidToken = Binder.clearCallingIdentity();
|
||||
try {
|
||||
ICancellationSignal cancellationSignal =
|
||||
service.onBeginGetCredential(request,
|
||||
new IBeginGetCredentialCallback.Stub() {
|
||||
@Override
|
||||
public void onSuccess(BeginGetCredentialResponse response) {
|
||||
getCredentials.complete(response);
|
||||
}
|
||||
service.onBeginGetCredential(request,
|
||||
new IBeginGetCredentialCallback.Stub() {
|
||||
@Override
|
||||
public void onSuccess(BeginGetCredentialResponse response) {
|
||||
getCredentials.complete(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String errorType, CharSequence message) {
|
||||
Log.i(TAG, "In onFailure in RemoteCredentialService");
|
||||
String errorMsg = message == null ? "" : String.valueOf(
|
||||
message);
|
||||
getCredentials.completeExceptionally(
|
||||
new GetCredentialException(errorType, errorMsg));
|
||||
}
|
||||
});
|
||||
cancellationSink.set(cancellationSignal);
|
||||
@Override
|
||||
public void onFailure(String errorType, CharSequence message) {
|
||||
Log.i(TAG, "In onFailure in RemoteCredentialService");
|
||||
String errorMsg = message == null ? "" : String.valueOf(
|
||||
message);
|
||||
getCredentials.completeExceptionally(
|
||||
new GetCredentialException(errorType, errorMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancellable(ICancellationSignal cancellation) {
|
||||
CompletableFuture<BeginGetCredentialResponse> future =
|
||||
futureRef.get();
|
||||
if (future != null && future.isCancelled()) {
|
||||
dispatchCancellationSignal(cancellation);
|
||||
} else {
|
||||
cancellationSink.set(cancellation);
|
||||
callback.onProviderCancellable(cancellation);
|
||||
}
|
||||
}
|
||||
});
|
||||
return getCredentials;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(originalCallingUidToken);
|
||||
}
|
||||
}).orTimeout(TIMEOUT_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
|
||||
futureRef.set(connectThenExecute);
|
||||
|
||||
connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
|
||||
handleExecutionResponse(result, error, cancellationSink, callback)));
|
||||
return cancellationSink.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -164,10 +180,12 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
* @param callback the callback to be used to send back the provider response to the
|
||||
* {@link ProviderCreateSession} class that maintains provider state
|
||||
*/
|
||||
public ICancellationSignal onCreateCredential(@NonNull BeginCreateCredentialRequest request,
|
||||
public void onBeginCreateCredential(@NonNull BeginCreateCredentialRequest request,
|
||||
ProviderCallbacks<BeginCreateCredentialResponse> callback) {
|
||||
Log.i(TAG, "In onCreateCredential in RemoteCredentialService");
|
||||
AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
|
||||
AtomicReference<CompletableFuture<BeginCreateCredentialResponse>> futureRef =
|
||||
new AtomicReference<>();
|
||||
|
||||
CompletableFuture<BeginCreateCredentialResponse> connectThenExecute =
|
||||
postAsync(service -> {
|
||||
@@ -175,7 +193,7 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
new CompletableFuture<>();
|
||||
final long originalCallingUidToken = Binder.clearCallingIdentity();
|
||||
try {
|
||||
ICancellationSignal cancellationSignal = service.onBeginCreateCredential(
|
||||
service.onBeginCreateCredential(
|
||||
request, new IBeginCreateCredentialCallback.Stub() {
|
||||
@Override
|
||||
public void onSuccess(BeginCreateCredentialResponse response) {
|
||||
@@ -192,18 +210,28 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
createCredentialFuture.completeExceptionally(
|
||||
new CreateCredentialException(errorType, errorMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancellable(ICancellationSignal cancellation) {
|
||||
CompletableFuture<BeginCreateCredentialResponse> future =
|
||||
futureRef.get();
|
||||
if (future != null && future.isCancelled()) {
|
||||
dispatchCancellationSignal(cancellation);
|
||||
} else {
|
||||
cancellationSink.set(cancellation);
|
||||
callback.onProviderCancellable(cancellation);
|
||||
}
|
||||
}
|
||||
});
|
||||
cancellationSink.set(cancellationSignal);
|
||||
return createCredentialFuture;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(originalCallingUidToken);
|
||||
}
|
||||
}).orTimeout(TIMEOUT_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
|
||||
futureRef.set(connectThenExecute);
|
||||
|
||||
connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
|
||||
handleExecutionResponse(result, error, cancellationSink, callback)));
|
||||
|
||||
return cancellationSink.get();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,10 +242,11 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
* @param callback the callback to be used to send back the provider response to the
|
||||
* {@link ProviderClearSession} class that maintains provider state
|
||||
*/
|
||||
public ICancellationSignal onClearCredentialState(@NonNull ClearCredentialStateRequest request,
|
||||
public void onClearCredentialState(@NonNull ClearCredentialStateRequest request,
|
||||
ProviderCallbacks<Void> callback) {
|
||||
Log.i(TAG, "In onClearCredentialState in RemoteCredentialService");
|
||||
AtomicReference<ICancellationSignal> cancellationSink = new AtomicReference<>();
|
||||
AtomicReference<CompletableFuture<Void>> futureRef = new AtomicReference<>();
|
||||
|
||||
CompletableFuture<Void> connectThenExecute =
|
||||
postAsync(service -> {
|
||||
@@ -225,7 +254,7 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
new CompletableFuture<>();
|
||||
final long originalCallingUidToken = Binder.clearCallingIdentity();
|
||||
try {
|
||||
ICancellationSignal cancellationSignal = service.onClearCredentialState(
|
||||
service.onClearCredentialState(
|
||||
request, new IClearCredentialStateCallback.Stub() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
@@ -243,18 +272,27 @@ public class RemoteCredentialService extends ServiceConnector.Impl<ICredentialPr
|
||||
new ClearCredentialStateException(errorType,
|
||||
errorMsg));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancellable(ICancellationSignal cancellation) {
|
||||
CompletableFuture<Void> future = futureRef.get();
|
||||
if (future != null && future.isCancelled()) {
|
||||
dispatchCancellationSignal(cancellation);
|
||||
} else {
|
||||
cancellationSink.set(cancellation);
|
||||
callback.onProviderCancellable(cancellation);
|
||||
}
|
||||
}
|
||||
});
|
||||
cancellationSink.set(cancellationSignal);
|
||||
return clearCredentialFuture;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(originalCallingUidToken);
|
||||
}
|
||||
}).orTimeout(TIMEOUT_REQUEST_MILLIS, TimeUnit.MILLISECONDS);
|
||||
futureRef.set(connectThenExecute);
|
||||
|
||||
connectThenExecute.whenComplete((result, error) -> Handler.getMain().post(() ->
|
||||
handleExecutionResponse(result, error, cancellationSink, callback)));
|
||||
|
||||
return cancellationSink.get();
|
||||
}
|
||||
|
||||
private <T> void handleExecutionResponse(T result,
|
||||
|
||||
Reference in New Issue
Block a user