From 72dd90b6c68df533878454884097cce8751a4487 Mon Sep 17 00:00:00 2001 From: Reema Bajwa Date: Thu, 29 Dec 2022 17:18:13 +0000 Subject: [PATCH] Remove pending intent from framework provider APIs Pending intents will be added to the Slice objects as slice actions through the jetpack library. Earlier, we needed this at the framework level as the framework was invoking the pending intent. We have now changed the design to have the UI app directly launch the pending intent. Test: Built locally Bug: 264717022 Change-Id: I2c62819bb4a60a55e9fbf7552ce2a7dc84dff3ee --- core/api/current.txt | 10 +- core/api/test-current.txt | 3 +- core/java/android/credentials/ui/Entry.java | 11 +- .../android/service/credentials/Action.java | 28 +- .../service/credentials/CreateEntry.java | 28 +- .../service/credentials/CredentialEntry.java | 83 ++--- .../CredentialManagerRepo.kt | 4 +- .../credentialmanager/DataConverter.kt | 312 +++++++++--------- .../server/credentials/GetRequestSession.java | 2 +- .../credentials/ProviderCreateSession.java | 8 +- .../credentials/ProviderGetSession.java | 25 +- 11 files changed, 230 insertions(+), 284 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index 6d3563133c65e..5f3b1f3e81c14 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -39769,9 +39769,8 @@ package android.service.controls.templates { package android.service.credentials { public class Action implements android.os.Parcelable { - ctor public Action(@NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent); + ctor public Action(@NonNull android.app.slice.Slice); method public int describeContents(); - method @NonNull public android.app.PendingIntent getPendingIntent(); method @NonNull public android.app.slice.Slice getSlice(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; @@ -39866,21 +39865,18 @@ package android.service.credentials { } public class CreateEntry implements android.os.Parcelable { - ctor public CreateEntry(@NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent); + ctor public CreateEntry(@NonNull android.app.slice.Slice); method public int describeContents(); - method @NonNull public android.app.PendingIntent getPendingIntent(); method @NonNull public android.app.slice.Slice getSlice(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; } public class CredentialEntry implements android.os.Parcelable { - ctor public CredentialEntry(@NonNull String, @NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent, boolean); + ctor public CredentialEntry(@NonNull String, @NonNull android.app.slice.Slice); method public int describeContents(); - method @NonNull public android.app.PendingIntent getPendingIntent(); method @NonNull public android.app.slice.Slice getSlice(); method @NonNull public String getType(); - method public boolean isAutoSelectAllowed(); method public void writeToParcel(@NonNull android.os.Parcel, int); field @NonNull public static final android.os.Parcelable.Creator CREATOR; } diff --git a/core/api/test-current.txt b/core/api/test-current.txt index f675f705d3729..e3554a5aa043b 100644 --- a/core/api/test-current.txt +++ b/core/api/test-current.txt @@ -997,7 +997,8 @@ package android.credentials.ui { public final class Entry implements android.os.Parcelable { ctor public Entry(@NonNull String, @NonNull String, @NonNull android.app.slice.Slice); - ctor public Entry(@NonNull String, @NonNull String, @NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent, @Nullable android.content.Intent); + ctor public Entry(@NonNull String, @NonNull String, @NonNull android.app.slice.Slice, @NonNull android.app.PendingIntent, @NonNull android.content.Intent); + ctor public Entry(@NonNull String, @NonNull String, @NonNull android.app.slice.Slice, @NonNull android.content.Intent); method public int describeContents(); method @Nullable public android.content.Intent getFrameworkExtrasIntent(); method @NonNull public String getKey(); diff --git a/core/java/android/credentials/ui/Entry.java b/core/java/android/credentials/ui/Entry.java index b7718ac54110f..9f2edae6d8e40 100644 --- a/core/java/android/credentials/ui/Entry.java +++ b/core/java/android/credentials/ui/Entry.java @@ -89,12 +89,21 @@ public final class Entry implements Parcelable { * when clicked. */ public Entry(@NonNull String key, @NonNull String subkey, @NonNull Slice slice, - @NonNull PendingIntent pendingIntent, @Nullable Intent intent) { + @NonNull PendingIntent pendingIntent, @NonNull Intent intent) { this(key, subkey, slice); mPendingIntent = pendingIntent; mFrameworkExtrasIntent = intent; } + /** Constructor to be used for an entry that requires a pending intent to be invoked + * when clicked. + */ + public Entry(@NonNull String key, @NonNull String subkey, @NonNull Slice slice, + @NonNull Intent intent) { + this(key, subkey, slice); + mFrameworkExtrasIntent = intent; + } + /** * Returns the identifier of this entry that's unique within the context of the CredentialManager * request. diff --git a/core/java/android/service/credentials/Action.java b/core/java/android/service/credentials/Action.java index e1875059e48b1..7487ac022c8e5 100644 --- a/core/java/android/service/credentials/Action.java +++ b/core/java/android/service/credentials/Action.java @@ -29,6 +29,9 @@ import java.util.Objects; * An action defined by the provider that intents into the provider's app for specific * user actions. * + *

If user selects this action entry, the corresponding {@link PendingIntent} set on the + * {@code slice} as a {@link androidx.slice.core.SliceAction} will get invoked. + * *

Any class that derives this class must only add extra field values to the {@code slice} * object passed into the constructor. Any other field will not be parceled through. If the * derived class has custom parceling implementation, this class will not be able to unpack @@ -37,9 +40,8 @@ import java.util.Objects; @SuppressLint("ParcelNotFinal") public class Action implements Parcelable { /** Slice object containing display content to be displayed with this action on the UI. */ - private final @NonNull Slice mSlice; - /** The pending intent to be invoked when the user selects this action. */ - private final @NonNull PendingIntent mPendingIntent; + @NonNull + private final Slice mSlice; /** * Constructs an action to be displayed on the UI. @@ -52,21 +54,18 @@ public class Action implements Parcelable { * {@link BeginCreateCredentialResponse} and {@link BeginGetCredentialResponse}. * * @param slice the display content to be displayed on the UI, along with this action - * @param pendingIntent the intent to be invoked when the user selects this action */ - public Action(@NonNull Slice slice, @NonNull PendingIntent pendingIntent) { + public Action(@NonNull Slice slice) { Objects.requireNonNull(slice, "slice must not be null"); - Objects.requireNonNull(pendingIntent, "pendingIntent must not be null"); mSlice = slice; - mPendingIntent = pendingIntent; } private Action(@NonNull Parcel in) { mSlice = in.readTypedObject(Slice.CREATOR); - mPendingIntent = in.readTypedObject(PendingIntent.CREATOR); } - public static final @NonNull Creator CREATOR = new Creator() { + @NonNull + public static final Creator CREATOR = new Creator() { @Override public Action createFromParcel(@NonNull Parcel in) { return new Action(in); @@ -86,20 +85,13 @@ public class Action implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeTypedObject(mSlice, flags); - dest.writeTypedObject(mPendingIntent, flags); } /** * Returns a {@code Slice} object containing the display content to be displayed on the UI. */ - public @NonNull Slice getSlice() { + @NonNull + public Slice getSlice() { return mSlice; } - - /** - * Returns the {@link PendingIntent} to be invoked when the action is selected. - */ - public @NonNull PendingIntent getPendingIntent() { - return mPendingIntent; - } } diff --git a/core/java/android/service/credentials/CreateEntry.java b/core/java/android/service/credentials/CreateEntry.java index 84a5f1cdb89bc..106e65c3d70e9 100644 --- a/core/java/android/service/credentials/CreateEntry.java +++ b/core/java/android/service/credentials/CreateEntry.java @@ -27,6 +27,13 @@ import android.os.Parcelable; * An entry to be shown on the UI. This entry represents where the credential to be created will * be stored. Examples include user's account, family group etc. * + *

If user selects this entry, the corresponding {@link PendingIntent} set on the + * {@code slice} as a {@link androidx.slice.core.SliceAction} will get invoked. + * Once the resulting activity fulfills the required user engagement, + * the {@link android.app.Activity} result should be set to {@link android.app.Activity#RESULT_OK}, + * and the {@link CredentialProviderService#EXTRA_CREATE_CREDENTIAL_RESPONSE} must be set with a + * {@link android.credentials.CreateCredentialResponse} object. + * *

Any class that derives this class must only add extra field values to the {@code slice} * object passed into the constructor. Any other field will not be parceled through. If the * derived class has custom parceling implementation, this class will not be able to unpack @@ -35,14 +42,13 @@ import android.os.Parcelable; @SuppressLint("ParcelNotFinal") public class CreateEntry implements Parcelable { private final @NonNull Slice mSlice; - private final @NonNull PendingIntent mPendingIntent; private CreateEntry(@NonNull Parcel in) { mSlice = in.readTypedObject(Slice.CREATOR); - mPendingIntent = in.readTypedObject(PendingIntent.CREATOR); } - public static final @NonNull Creator CREATOR = new Creator() { + @NonNull + public static final Creator CREATOR = new Creator() { @Override public CreateEntry createFromParcel(@NonNull Parcel in) { return new CreateEntry(in); @@ -62,33 +68,23 @@ public class CreateEntry implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeTypedObject(mSlice, flags); - dest.writeTypedObject(mPendingIntent, flags); } /** * Constructs a CreateEntry to be displayed on the UI. * * @param slice the display content to be displayed on the UI, along with this entry - * @param pendingIntent the intent to be invoked when the user selects this entry */ public CreateEntry( - @NonNull Slice slice, - @NonNull PendingIntent pendingIntent) { + @NonNull Slice slice) { this.mSlice = slice; com.android.internal.util.AnnotationValidations.validate( NonNull.class, null, mSlice); - this.mPendingIntent = pendingIntent; - com.android.internal.util.AnnotationValidations.validate( - NonNull.class, null, mPendingIntent); } /** Returns the content to be displayed with this create entry on the UI. */ - public @NonNull Slice getSlice() { + @NonNull + public Slice getSlice() { return mSlice; } - - /** Returns the pendingIntent to be invoked when this create entry on the UI is selectcd. */ - public @NonNull PendingIntent getPendingIntent() { - return mPendingIntent; - } } diff --git a/core/java/android/service/credentials/CredentialEntry.java b/core/java/android/service/credentials/CredentialEntry.java index 21e7b805c2bbd..b03726825488a 100644 --- a/core/java/android/service/credentials/CredentialEntry.java +++ b/core/java/android/service/credentials/CredentialEntry.java @@ -24,17 +24,14 @@ import android.credentials.GetCredentialResponse; import android.os.Parcel; import android.os.Parcelable; -import com.android.internal.util.Preconditions; - -import java.util.Objects; - /** * A credential entry that is to be displayed on the account selector that is presented to the * user. * - *

If user selects this entry, the corresponding {@code pendingIntent} will be invoked to - * launch activities that require some user engagement before getting the credential - * corresponding to this entry, e.g. authentication, confirmation etc. + *

If user selects this entry, the corresponding {@link PendingIntent}, + * set on the {@code slice} as a {@link androidx.slice.core.SliceAction} will be + * invoked to launch activities that require some user engagement before getting + * the credential corresponding to this entry, e.g. authentication, confirmation etc. * * Once the activity fulfills the required user engagement, the {@link android.app.Activity} * result should be set to {@link android.app.Activity#RESULT_OK}, and the @@ -55,51 +52,29 @@ public class CredentialEntry implements Parcelable { * on the UI. */ private final @NonNull Slice mSlice; - /** The pending intent to be invoked when this credential entry is selected. */ - private final @NonNull PendingIntent mPendingIntent; - - /** A flag denoting whether auto-select is enabled for this entry. */ - private final boolean mAutoSelectAllowed; - - /** - * Constructs an instance of the credential entry to be displayed on the UI - * @param type the type of credential underlying this credential entry - * @param slice the content to be displayed with this entry on the UI - * @param pendingIntent the pendingIntent to be invoked when this entry is selected by the user - * @param autoSelectAllowed whether this entry should be auto selected if it is the only one - * on the selector - * - * @throws NullPointerException If {@code slice}, or {@code pendingIntent} is null. - * @throws IllegalArgumentException If {@code type} is null or empty, or if - * {@code pendingIntent} is null. - */ - public CredentialEntry(@NonNull String type, @NonNull Slice slice, - @NonNull PendingIntent pendingIntent, boolean autoSelectAllowed) { - mType = Preconditions.checkStringNotEmpty(type, "type must not be null"); - mSlice = Objects.requireNonNull(slice, "slice must not be null"); - mPendingIntent = Objects.requireNonNull(pendingIntent, "pendingintent must not be null"); - mAutoSelectAllowed = autoSelectAllowed; + public CredentialEntry(@NonNull String type, @NonNull Slice slice) { + mType = type; + mSlice = slice; } private CredentialEntry(@NonNull Parcel in) { mType = in.readString8(); mSlice = in.readTypedObject(Slice.CREATOR); - mPendingIntent = in.readTypedObject(PendingIntent.CREATOR); - mAutoSelectAllowed = in.readBoolean(); } - public static final @NonNull Creator CREATOR = + @NonNull + public static final Creator CREATOR = new Creator() { - @Override - public CredentialEntry createFromParcel(@NonNull Parcel in) { - return new CredentialEntry(in); - } + @Override + public CredentialEntry createFromParcel(@NonNull Parcel in) { + return new CredentialEntry(in); + } - @Override - public CredentialEntry[] newArray(int size) { - return new CredentialEntry[size]; - } - }; + @Override + public CredentialEntry[] newArray(int size) { + return new CredentialEntry[size]; + } + }; @Override public int describeContents() { @@ -110,35 +85,21 @@ public class CredentialEntry implements Parcelable { public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString8(mType); dest.writeTypedObject(mSlice, flags); - dest.writeTypedObject(mPendingIntent, flags); - dest.writeBoolean(mAutoSelectAllowed); } /** * Returns the specific credential type of the entry. */ - public @NonNull String getType() { + @NonNull + public String getType() { return mType; } /** * Returns the {@link Slice} object containing UI display content to be shown for this entry. */ - public @NonNull Slice getSlice() { + @NonNull + public Slice getSlice() { return mSlice; } - - /** - * Returns the pending intent to be invoked if the user selects this entry. - */ - public @NonNull PendingIntent getPendingIntent() { - return mPendingIntent; - } - - /** - * Returns whether this entry can be auto selected if it is the only option for the user. - */ - public boolean isAutoSelectAllowed() { - return mAutoSelectAllowed; - } } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt index a146059873226..0e3772abc9505 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt @@ -325,7 +325,6 @@ class CredentialManagerRepo( key, subkey, CredentialEntry.toSlice(credentialEntry), - pendingIntent, null ) } @@ -366,8 +365,7 @@ class CredentialManagerRepo( key, subkey, CreateEntry.toSlice(createEntry), - pendingIntent, - fillInIntent, + fillInIntent ) } diff --git a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt index e667ebd283ea1..217f8f9fa5279 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt @@ -53,8 +53,8 @@ class GetFlowUtils { companion object { fun toProviderList( - providerDataList: List, - context: Context, + providerDataList: List, + context: Context, ): List { val packageManager = context.packageManager return providerDataList.map { @@ -67,45 +67,45 @@ class GetFlowUtils { } val pkgInfo = packageManager - .getPackageInfo(packageName!!, - PackageManager.PackageInfoFlags.of(0)) + .getPackageInfo(packageName!!, + PackageManager.PackageInfoFlags.of(0)) val providerDisplayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString() // TODO: get the provider icon from the service // and decide what to do when failed to load a provider icon val providerIcon = pkgInfo.applicationInfo.loadIcon(packageManager)!! ProviderInfo( - id = it.providerFlattenedComponentName, - // TODO: decide what to do when failed to load a provider icon - icon = providerIcon, - displayName = providerDisplayName, - credentialEntryList = getCredentialOptionInfoList( - it.providerFlattenedComponentName, it.credentialEntries, context), - authenticationEntry = getAuthenticationEntry( - it.providerFlattenedComponentName, - providerDisplayName, - providerIcon, - it.authenticationEntry), - remoteEntry = getRemoteEntry(it.providerFlattenedComponentName, it.remoteEntry), - actionEntryList = getActionEntryList( - it.providerFlattenedComponentName, it.actionChips, providerIcon), + id = it.providerFlattenedComponentName, + // TODO: decide what to do when failed to load a provider icon + icon = providerIcon, + displayName = providerDisplayName, + credentialEntryList = getCredentialOptionInfoList( + it.providerFlattenedComponentName, it.credentialEntries, context), + authenticationEntry = getAuthenticationEntry( + it.providerFlattenedComponentName, + providerDisplayName, + providerIcon, + it.authenticationEntry), + remoteEntry = getRemoteEntry(it.providerFlattenedComponentName, it.remoteEntry), + actionEntryList = getActionEntryList( + it.providerFlattenedComponentName, it.actionChips, providerIcon), ) } } fun toRequestDisplayInfo( - requestInfo: RequestInfo, + requestInfo: RequestInfo, ): com.android.credentialmanager.getflow.RequestDisplayInfo { return com.android.credentialmanager.getflow.RequestDisplayInfo( - appDomainName = requestInfo.appPackageName + appDomainName = requestInfo.appPackageName ) } /* From service data structure to UI credential entry list representation. */ private fun getCredentialOptionInfoList( - providerId: String, - credentialEntries: List, - context: Context, + providerId: String, + credentialEntries: List, + context: Context, ): List { return credentialEntries.map { // TODO: handle NPE gracefully @@ -113,27 +113,27 @@ class GetFlowUtils { // Consider directly move the UI object into the class. return@map CredentialEntryInfo( - providerId = providerId, - entryKey = it.key, - entrySubkey = it.subkey, - pendingIntent = it.pendingIntent, - fillInIntent = it.frameworkExtrasIntent, - credentialType = credentialEntry.type.toString(), - credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(), - userName = credentialEntry.username.toString(), - displayName = credentialEntry.displayName?.toString(), - // TODO: proper fallback - icon = credentialEntry.icon?.loadDrawable(context), - lastUsedTimeMillis = credentialEntry.lastUsedTimeMillis, + providerId = providerId, + entryKey = it.key, + entrySubkey = it.subkey, + pendingIntent = credentialEntry.pendingIntent, + fillInIntent = it.frameworkExtrasIntent, + credentialType = credentialEntry.type.toString(), + credentialTypeDisplayName = credentialEntry.typeDisplayName.toString(), + userName = credentialEntry.username.toString(), + displayName = credentialEntry.displayName?.toString(), + // TODO: proper fallback + icon = credentialEntry.icon?.loadDrawable(context), + lastUsedTimeMillis = credentialEntry.lastUsedTimeMillis, ) } } private fun getAuthenticationEntry( - providerId: String, - providerDisplayName: String, - providerIcon: Drawable, - authEntry: Entry?, + providerId: String, + providerDisplayName: String, + providerIcon: Drawable, + authEntry: Entry?, ): AuthenticationEntryInfo? { // TODO: should also call fromSlice after getting the official jetpack code. @@ -141,13 +141,13 @@ class GetFlowUtils { return null } return AuthenticationEntryInfo( - providerId = providerId, - entryKey = authEntry.key, - entrySubkey = authEntry.subkey, - pendingIntent = authEntry.pendingIntent, - fillInIntent = authEntry.frameworkExtrasIntent, - title = providerDisplayName, - icon = providerIcon, + providerId = providerId, + entryKey = authEntry.key, + entrySubkey = authEntry.subkey, + pendingIntent = authEntry.pendingIntent, + fillInIntent = authEntry.frameworkExtrasIntent, + title = providerDisplayName, + icon = providerIcon, ) } @@ -157,33 +157,33 @@ class GetFlowUtils { return null } return RemoteEntryInfo( - providerId = providerId, - entryKey = remoteEntry.key, - entrySubkey = remoteEntry.subkey, - pendingIntent = remoteEntry.pendingIntent, - fillInIntent = remoteEntry.frameworkExtrasIntent, + providerId = providerId, + entryKey = remoteEntry.key, + entrySubkey = remoteEntry.subkey, + pendingIntent = remoteEntry.pendingIntent, + fillInIntent = remoteEntry.frameworkExtrasIntent, ) } private fun getActionEntryList( - providerId: String, - actionEntries: List, - providerIcon: Drawable, + providerId: String, + actionEntries: List, + providerIcon: Drawable, ): List { return actionEntries.map { // TODO: handle NPE gracefully val actionEntryUi = Action.fromSlice(it.slice)!! return@map ActionEntryInfo( - providerId = providerId, - entryKey = it.key, - entrySubkey = it.subkey, - pendingIntent = it.pendingIntent, - fillInIntent = it.frameworkExtrasIntent, - title = actionEntryUi.title.toString(), - // TODO: gracefully fail - icon = providerIcon, - subTitle = actionEntryUi.subTitle?.toString(), + providerId = providerId, + entryKey = it.key, + entrySubkey = it.subkey, + pendingIntent = actionEntryUi.pendingIntent, + fillInIntent = it.frameworkExtrasIntent, + title = actionEntryUi.title.toString(), + // TODO: gracefully fail + icon = providerIcon, + subTitle = actionEntryUi.subTitle?.toString(), ) } } @@ -194,8 +194,8 @@ class CreateFlowUtils { companion object { fun toEnabledProviderList( - providerDataList: List, - context: Context, + providerDataList: List, + context: Context, ): List { // TODO: get from the actual service info val packageManager = context.packageManager @@ -209,23 +209,23 @@ class CreateFlowUtils { } val pkgInfo = packageManager - .getPackageInfo(packageName!!, - PackageManager.PackageInfoFlags.of(0)) + .getPackageInfo(packageName!!, + PackageManager.PackageInfoFlags.of(0)) EnabledProviderInfo( - // TODO: decide what to do when failed to load a provider icon - icon = pkgInfo.applicationInfo.loadIcon(packageManager)!!, - name = it.providerFlattenedComponentName, - displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(), - createOptions = toCreationOptionInfoList( - it.providerFlattenedComponentName, it.saveEntries, context), - remoteEntry = toRemoteInfo(it.providerFlattenedComponentName, it.remoteEntry), + // TODO: decide what to do when failed to load a provider icon + icon = pkgInfo.applicationInfo.loadIcon(packageManager)!!, + name = it.providerFlattenedComponentName, + displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(), + createOptions = toCreationOptionInfoList( + it.providerFlattenedComponentName, it.saveEntries, context), + remoteEntry = toRemoteInfo(it.providerFlattenedComponentName, it.remoteEntry), ) } } fun toDisabledProviderList( - providerDataList: List?, - context: Context, + providerDataList: List?, + context: Context, ): List? { // TODO: get from the actual service info val packageManager = context.packageManager @@ -240,31 +240,31 @@ class CreateFlowUtils { .getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0)) DisabledProviderInfo( - icon = pkgInfo.applicationInfo.loadIcon(packageManager)!!, - name = it.providerFlattenedComponentName, - displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(), + icon = pkgInfo.applicationInfo.loadIcon(packageManager)!!, + name = it.providerFlattenedComponentName, + displayName = pkgInfo.applicationInfo.loadLabel(packageManager).toString(), ) } } fun toRequestDisplayInfo( - requestInfo: RequestInfo, - context: Context, + requestInfo: RequestInfo, + context: Context, ): RequestDisplayInfo { val createCredentialRequest = requestInfo.createCredentialRequest val createCredentialRequestJetpack = createCredentialRequest?.let { CreateCredentialRequest.createFrom( - it + it ) } when (createCredentialRequestJetpack) { is CreatePasswordRequest -> { return RequestDisplayInfo( - createCredentialRequestJetpack.id, - createCredentialRequestJetpack.password, - createCredentialRequestJetpack.type, - requestInfo.appPackageName, - context.getDrawable(R.drawable.ic_password)!! + createCredentialRequestJetpack.id, + createCredentialRequestJetpack.password, + createCredentialRequestJetpack.type, + requestInfo.appPackageName, + context.getDrawable(R.drawable.ic_password)!! ) } is CreatePublicKeyCredentialRequest -> { @@ -278,31 +278,31 @@ class CreateFlowUtils { displayName = user.getString("displayName") } return RequestDisplayInfo( - name, - displayName, - createCredentialRequestJetpack.type, - requestInfo.appPackageName, - context.getDrawable(R.drawable.ic_passkey)!!) + name, + displayName, + createCredentialRequestJetpack.type, + requestInfo.appPackageName, + context.getDrawable(R.drawable.ic_passkey)!!) } // TODO: correctly parsing for other sign-ins else -> { return RequestDisplayInfo( - "beckett-bakert@gmail.com", - "Elisa Beckett", - "other-sign-ins", - requestInfo.appPackageName, - context.getDrawable(R.drawable.ic_other_sign_in)!!) + "beckett-bakert@gmail.com", + "Elisa Beckett", + "other-sign-ins", + requestInfo.appPackageName, + context.getDrawable(R.drawable.ic_other_sign_in)!!) } } } fun toCreateCredentialUiState( - enabledProviders: List, - disabledProviders: List?, - defaultProviderId: String?, - requestDisplayInfo: RequestDisplayInfo, - isOnPasskeyIntroStateAlready: Boolean, - isPasskeyFirstUse: Boolean, + enabledProviders: List, + disabledProviders: List?, + defaultProviderId: String?, + requestDisplayInfo: RequestDisplayInfo, + isOnPasskeyIntroStateAlready: Boolean, + isPasskeyFirstUse: Boolean, ): CreateCredentialUiState { var lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo? = null var remoteEntry: RemoteInfo? = null @@ -310,7 +310,7 @@ class CreateFlowUtils { var createOptionsPairs: MutableList> = mutableListOf() enabledProviders.forEach { - enabledProvider -> + enabledProvider -> if (defaultProviderId != null) { if (enabledProvider.id == defaultProviderId) { defaultProvider = enabledProvider @@ -327,10 +327,10 @@ class CreateFlowUtils { } } return CreateCredentialUiState( - enabledProviders = enabledProviders, - disabledProviders = disabledProviders, - toCreateScreenState( - /*createOptionSize=*/createOptionsPairs.size, + enabledProviders = enabledProviders, + disabledProviders = disabledProviders, + toCreateScreenState( + /*createOptionSize=*/createOptionsPairs.size, /*isOnPasskeyIntroStateAlready=*/isOnPasskeyIntroStateAlready, /*requestDisplayInfo=*/requestDisplayInfo, /*defaultProvider=*/defaultProvider, /*remoteEntry=*/remoteEntry, @@ -341,31 +341,32 @@ class CreateFlowUtils { toActiveEntry( /*defaultProvider=*/defaultProvider, /*createOptionSize=*/createOptionsPairs.size, - /*lastSeenProviderWithNonEmptyCreateOptions=*/lastSeenProviderWithNonEmptyCreateOptions, - /*remoteEntry=*/remoteEntry), + /*lastSeenProviderWithNonEmptyCreateOptions=*/ + lastSeenProviderWithNonEmptyCreateOptions, + /*remoteEntry=*/remoteEntry), ) } private fun toCreateScreenState( - createOptionSize: Int, - isOnPasskeyIntroStateAlready: Boolean, - requestDisplayInfo: RequestDisplayInfo, - defaultProvider: EnabledProviderInfo?, - remoteEntry: RemoteInfo?, - isPasskeyFirstUse: Boolean, + createOptionSize: Int, + isOnPasskeyIntroStateAlready: Boolean, + requestDisplayInfo: RequestDisplayInfo, + defaultProvider: EnabledProviderInfo?, + remoteEntry: RemoteInfo?, + isPasskeyFirstUse: Boolean, ): CreateScreenState { return if ( - isPasskeyFirstUse && requestDisplayInfo - .type == TYPE_PUBLIC_KEY_CREDENTIAL && !isOnPasskeyIntroStateAlready) { + isPasskeyFirstUse && requestDisplayInfo + .type == TYPE_PUBLIC_KEY_CREDENTIAL && !isOnPasskeyIntroStateAlready) { CreateScreenState.PASSKEY_INTRO } else if ( - (defaultProvider == null || defaultProvider.createOptions.isEmpty() - ) && createOptionSize > 1) { + (defaultProvider == null || defaultProvider.createOptions.isEmpty() + ) && createOptionSize > 1) { CreateScreenState.PROVIDER_SELECTION } else if ( - ((defaultProvider == null || defaultProvider.createOptions.isEmpty() - ) && createOptionSize == 1) || ( - defaultProvider != null && defaultProvider.createOptions.isNotEmpty())) { + ((defaultProvider == null || defaultProvider.createOptions.isEmpty() + ) && createOptionSize == 1) || ( + defaultProvider != null && defaultProvider.createOptions.isNotEmpty())) { CreateScreenState.CREATION_OPTION_SELECTION } else if (createOptionSize == 0 && remoteEntry != null) { CreateScreenState.EXTERNAL_ONLY_SELECTION @@ -376,65 +377,66 @@ class CreateFlowUtils { } private fun toActiveEntry( - defaultProvider: EnabledProviderInfo?, - createOptionSize: Int, - lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo?, - remoteEntry: RemoteInfo?, + defaultProvider: EnabledProviderInfo?, + createOptionSize: Int, + lastSeenProviderWithNonEmptyCreateOptions: EnabledProviderInfo?, + remoteEntry: RemoteInfo?, ): ActiveEntry? { return if ( - defaultProvider != null && defaultProvider.createOptions.isEmpty() && remoteEntry != null) { + defaultProvider != null && defaultProvider.createOptions.isEmpty() && + remoteEntry != null) { ActiveEntry(defaultProvider, remoteEntry) } else if ( - defaultProvider != null && defaultProvider.createOptions.isNotEmpty() + defaultProvider != null && defaultProvider.createOptions.isNotEmpty() ) { ActiveEntry(defaultProvider, defaultProvider.createOptions.first()) } else if (createOptionSize == 1) { ActiveEntry(lastSeenProviderWithNonEmptyCreateOptions!!, - lastSeenProviderWithNonEmptyCreateOptions.createOptions.first()) + lastSeenProviderWithNonEmptyCreateOptions.createOptions.first()) } else null } private fun toCreationOptionInfoList( - providerId: String, - creationEntries: List, - context: Context, + providerId: String, + creationEntries: List, + context: Context, ): List { return creationEntries.map { // TODO: handle NPE gracefully val createEntry = CreateEntry.fromSlice(it.slice)!! return@map CreateOptionInfo( - // TODO: remove fallbacks - providerId = providerId, - entryKey = it.key, - entrySubkey = it.subkey, - pendingIntent = it.pendingIntent, - fillInIntent = it.frameworkExtrasIntent, - userProviderDisplayName = createEntry.accountName.toString(), - profileIcon = createEntry.icon?.loadDrawable(context), - passwordCount = CredentialCountInformation.getPasswordCount( - createEntry.credentialCountInformationList) ?: 0, - passkeyCount = CredentialCountInformation.getPasskeyCount( - createEntry.credentialCountInformationList) ?: 0, - totalCredentialCount = CredentialCountInformation.getTotalCount( - createEntry.credentialCountInformationList) ?: 0, - lastUsedTimeMillis = createEntry.lastUsedTimeMillis ?: 0, + // TODO: remove fallbacks + providerId = providerId, + entryKey = it.key, + entrySubkey = it.subkey, + pendingIntent = createEntry.pendingIntent, + fillInIntent = it.frameworkExtrasIntent, + userProviderDisplayName = createEntry.accountName.toString(), + profileIcon = createEntry.icon?.loadDrawable(context), + passwordCount = CredentialCountInformation.getPasswordCount( + createEntry.credentialCountInformationList) ?: 0, + passkeyCount = CredentialCountInformation.getPasskeyCount( + createEntry.credentialCountInformationList) ?: 0, + totalCredentialCount = CredentialCountInformation.getTotalCount( + createEntry.credentialCountInformationList) ?: 0, + lastUsedTimeMillis = createEntry.lastUsedTimeMillis ?: 0, ) } } private fun toRemoteInfo( - providerId: String, - remoteEntry: Entry?, + providerId: String, + remoteEntry: Entry?, ): RemoteInfo? { // TODO: should also call fromSlice after getting the official jetpack code. return if (remoteEntry != null) { RemoteInfo( - providerId = providerId, - entryKey = remoteEntry.key, - entrySubkey = remoteEntry.subkey, - pendingIntent = remoteEntry.pendingIntent, - fillInIntent = remoteEntry.frameworkExtrasIntent, + providerId = providerId, + entryKey = remoteEntry.key, + entrySubkey = remoteEntry.subkey, + pendingIntent = remoteEntry.pendingIntent, + fillInIntent = remoteEntry.frameworkExtrasIntent, ) } else null } diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java index 09ff2afabeb1d..06396e003745f 100644 --- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java @@ -72,7 +72,7 @@ public final class GetRequestSession extends RequestSession(entryId, authenticationAction); return authEntry; } @@ -304,20 +303,15 @@ public final class ProviderGetSession extends ProviderSession