Merge "Send intent for UI when providers are updated"

This commit is contained in:
TreeHugger Robot
2023-01-06 22:59:10 +00:00
committed by Android (Google) Code Review
3 changed files with 97 additions and 54 deletions

View File

@@ -24,9 +24,12 @@ package android.credentials.ui;
public class Constants {
/**
* The intent extra key for the {@code ResultReceiver} object when launching the UX
* activities.
*/
* The intent extra key for the {@code ResultReceiver} object when launching the UX activities.
*/
public static final String EXTRA_RESULT_RECEIVER =
"android.credentials.ui.extra.RESULT_RECEIVER";
/** The intent action for when the enabled Credential Manager providers has been updated. */
public static final String CREDMAN_ENABLED_PROVIDERS_UPDATED =
"android.credentials.ui.action.CREDMAN_ENABLED_PROVIDERS_UPDATED";
}

View File

@@ -39,14 +39,19 @@ public class IntentFactory {
public static Intent createCredentialSelectorIntent(
@NonNull RequestInfo requestInfo,
@SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling.
@NonNull ArrayList<ProviderData> enabledProviderDataList,
@NonNull
ArrayList<ProviderData> enabledProviderDataList,
@SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling.
@NonNull ArrayList<DisabledProviderData> disabledProviderDataList,
@NonNull
ArrayList<DisabledProviderData> disabledProviderDataList,
@NonNull ResultReceiver resultReceiver) {
Intent intent = new Intent();
ComponentName componentName = ComponentName.unflattenFromString(
Resources.getSystem().getString(
com.android.internal.R.string.config_credentialManagerDialogComponent));
ComponentName componentName =
ComponentName.unflattenFromString(
Resources.getSystem()
.getString(
com.android.internal.R.string
.config_credentialManagerDialogComponent));
intent.setComponent(componentName);
intent.putParcelableArrayListExtra(
@@ -54,17 +59,35 @@ public class IntentFactory {
intent.putParcelableArrayListExtra(
ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST, disabledProviderDataList);
intent.putExtra(RequestInfo.EXTRA_REQUEST_INFO, requestInfo);
intent.putExtra(Constants.EXTRA_RESULT_RECEIVER,
toIpcFriendlyResultReceiver(resultReceiver));
intent.putExtra(
Constants.EXTRA_RESULT_RECEIVER, toIpcFriendlyResultReceiver(resultReceiver));
return intent;
}
/**
* Convert an instance of a "locally-defined" ResultReceiver to an instance of
* {@link android.os.ResultReceiver} itself, which the receiving process will be able to
* unmarshall.
*/
* Notify the UI that providers have been enabled/disabled.
*
* @hide
*/
@NonNull
public static Intent createProviderUpdateIntent() {
Intent intent = new Intent();
ComponentName componentName =
ComponentName.unflattenFromString(
Resources.getSystem()
.getString(
com.android.internal.R.string
.config_credentialManagerDialogComponent));
intent.setComponent(componentName);
intent.setAction(Constants.CREDMAN_ENABLED_PROVIDERS_UPDATED);
return intent;
}
/**
* Convert an instance of a "locally-defined" ResultReceiver to an instance of {@link
* android.os.ResultReceiver} itself, which the receiving process will be able to unmarshall.
*/
private static <T extends ResultReceiver> ResultReceiver toIpcFriendlyResultReceiver(
T resultReceiver) {
final Parcel parcel = Parcel.obtain();

View File

@@ -35,6 +35,7 @@ import android.credentials.IGetCredentialCallback;
import android.credentials.IListEnabledProvidersCallback;
import android.credentials.ISetEnabledProvidersCallback;
import android.credentials.ListEnabledProvidersResponse;
import android.credentials.ui.IntentFactory;
import android.os.Binder;
import android.os.CancellationSignal;
import android.os.ICancellationSignal;
@@ -115,9 +116,8 @@ public final class CredentialManagerService
continue;
}
try {
serviceList.add(new CredentialManagerServiceImpl(this, mLock,
resolvedUserId,
serviceName));
serviceList.add(
new CredentialManagerServiceImpl(this, mLock, resolvedUserId, serviceName));
} catch (PackageManager.NameNotFoundException | SecurityException e) {
Log.i(TAG, "Unable to add serviceInfo : " + e.getMessage());
}
@@ -175,15 +175,17 @@ public final class CredentialManagerService
RequestSession session, List<String> requestOptions) {
List<ProviderSession> providerSessions = new ArrayList<>();
// Invoke all services of a user to initiate a provider session
runForUser((service) -> {
synchronized (mLock) {
ProviderSession providerSession = service
.initiateProviderSessionForRequestLocked(session, requestOptions);
if (providerSession != null) {
providerSessions.add(providerSession);
}
}
});
runForUser(
(service) -> {
synchronized (mLock) {
ProviderSession providerSession =
service.initiateProviderSessionForRequestLocked(
session, requestOptions);
if (providerSession != null) {
providerSessions.add(providerSession);
}
}
});
return providerSessions;
}
@@ -208,27 +210,35 @@ public final class CredentialManagerService
// Initiate all provider sessions
List<ProviderSession> providerSessions =
initiateProviderSessions(session, request.getGetCredentialOptions()
.stream().map(GetCredentialOption::getType)
.collect(Collectors.toList()));
initiateProviderSessions(
session,
request.getGetCredentialOptions().stream()
.map(GetCredentialOption::getType)
.collect(Collectors.toList()));
if (providerSessions.isEmpty()) {
try {
// TODO("Replace with properly defined error type")
callback.onError("unknown_type",
"No providers available to fulfill request.");
callback.onError("unknown_type", "No providers available to fulfill request.");
} catch (RemoteException e) {
Log.i(TAG, "Issue invoking onError on IGetCredentialCallback "
+ "callback: " + e.getMessage());
Log.i(
TAG,
"Issue invoking onError on IGetCredentialCallback "
+ "callback: "
+ e.getMessage());
}
}
// Iterate over all provider sessions and invoke the request
providerSessions.forEach(providerGetSession -> {
providerGetSession.getRemoteCredentialService().onBeginGetCredential(
(BeginGetCredentialRequest) providerGetSession.getProviderRequest(),
/*callback=*/providerGetSession);
});
providerSessions.forEach(
providerGetSession -> {
providerGetSession
.getRemoteCredentialService()
.onBeginGetCredential(
(BeginGetCredentialRequest)
providerGetSession.getProviderRequest(),
/* callback= */ providerGetSession);
});
return cancelTransport;
}
@@ -257,11 +267,13 @@ public final class CredentialManagerService
if (providerSessions.isEmpty()) {
try {
// TODO("Replace with properly defined error type")
callback.onError("unknown_type",
"No providers available to fulfill request.");
callback.onError("unknown_type", "No providers available to fulfill request.");
} catch (RemoteException e) {
Log.i(TAG, "Issue invoking onError on ICreateCredentialCallback "
+ "callback: " + e.getMessage());
Log.i(
TAG,
"Issue invoking onError on ICreateCredentialCallback "
+ "callback: "
+ e.getMessage());
}
}
@@ -278,7 +290,7 @@ public final class CredentialManagerService
return cancelTransport;
}
@SuppressWarnings("GuardedBy") // ErrorProne requires listEnabledProviders
@SuppressWarnings("GuardedBy") // ErrorProne requires listEnabledProviders
// to be guarded by 'service.mLock', which is the same as mLock.
@Override
public ICancellationSignal listEnabledProviders(IListEnabledProvidersCallback callback) {
@@ -288,8 +300,7 @@ public final class CredentialManagerService
List<String> enabledProviders = new ArrayList<>();
runForUser(
(service) -> {
enabledProviders.add(
service.getComponentName().flattenToString());
enabledProviders.add(service.getComponentName().flattenToString());
});
// Call the callback.
@@ -331,7 +342,7 @@ public final class CredentialManagerService
"Failed to store setting containing enabled providers");
} catch (RemoteException e) {
Log.i(TAG, "Issue with invoking error response: " + e.getMessage());
// TODO: Propagate failure
return;
}
}
@@ -342,11 +353,16 @@ public final class CredentialManagerService
Log.i(TAG, "Issue with invoking response: " + e.getMessage());
// TODO: Propagate failure
}
// Send an intent to the UI that we have new enabled providers.
getContext().sendBroadcast(IntentFactory.createProviderUpdateIntent());
}
@Override
public ICancellationSignal clearCredentialState(ClearCredentialStateRequest request,
IClearCredentialStateCallback callback, String callingPackage) {
public ICancellationSignal clearCredentialState(
ClearCredentialStateRequest request,
IClearCredentialStateCallback callback,
String callingPackage) {
Log.i(TAG, "starting clearCredentialState with callingPackage: " + callingPackage);
// TODO : Implement cancellation
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
@@ -362,17 +378,18 @@ public final class CredentialManagerService
// Initiate all provider sessions
// TODO: Determine if provider needs to have clear capability in their manifest
List<ProviderSession> providerSessions =
initiateProviderSessions(session, List.of());
List<ProviderSession> providerSessions = initiateProviderSessions(session, List.of());
if (providerSessions.isEmpty()) {
try {
// TODO("Replace with properly defined error type")
callback.onError("unknown_type",
"No providers available to fulfill request.");
callback.onError("unknown_type", "No providers available to fulfill request.");
} catch (RemoteException e) {
Log.i(TAG, "Issue invoking onError on IClearCredentialStateCallback "
+ "callback: " + e.getMessage());
Log.i(
TAG,
"Issue invoking onError on IClearCredentialStateCallback "
+ "callback: "
+ e.getMessage());
}
}