From 2b2e8343c3b5c7bb82cfca29151dbf166bb77035 Mon Sep 17 00:00:00 2001 From: Helen Qin Date: Fri, 21 Oct 2022 07:06:17 +0000 Subject: Define the UI result code and corresponding data structures. Test: deployed locally Bug: 247855226 Bug: 253156958 Change-Id: I489e4f44b09030bba20075eb3c174e9f5275e5ac --- .../android/credentials/ui/BaseDialogResult.java | 123 +++++++++++++++++++++ .../credentials/ui/ProviderDialogResult.java | 100 +++++++++++++++++ .../credentials/ui/UserSelectionDialogResult.java | 116 +++++++++++++++++++ .../credentials/ui/UserSelectionResult.java | 112 ------------------- .../credentialmanager/CredentialManagerRepo.kt | 17 ++- 5 files changed, 347 insertions(+), 121 deletions(-) create mode 100644 core/java/android/credentials/ui/BaseDialogResult.java create mode 100644 core/java/android/credentials/ui/ProviderDialogResult.java create mode 100644 core/java/android/credentials/ui/UserSelectionDialogResult.java delete mode 100644 core/java/android/credentials/ui/UserSelectionResult.java diff --git a/core/java/android/credentials/ui/BaseDialogResult.java b/core/java/android/credentials/ui/BaseDialogResult.java new file mode 100644 index 000000000000..cf5f0363208a --- /dev/null +++ b/core/java/android/credentials/ui/BaseDialogResult.java @@ -0,0 +1,123 @@ +/* + * 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.ui; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.AnnotationValidations; + +/** + * Base dialog result data. + * + * Returned for simple use cases like cancellation. Can also be subclassed when more information + * is needed, e.g. {@link UserSelectionDialogResult}. + * + * @hide + */ +public class BaseDialogResult implements Parcelable { + /** Parses and returns a BaseDialogResult from the given resultData. */ + @Nullable + public static BaseDialogResult fromResultData(@NonNull Bundle resultData) { + return resultData.getParcelable(EXTRA_BASE_RESULT, BaseDialogResult.class); + } + + /** + * Used for the UX to construct the {@code resultData Bundle} to send via the {@code + * ResultReceiver}. + */ + public static void addToBundle(@NonNull BaseDialogResult result, @NonNull Bundle bundle) { + bundle.putParcelable(EXTRA_BASE_RESULT, result); + } + + /** + * The intent extra key for the {@code BaseDialogResult} object when the credential + * selector activity finishes. + */ + private static final String EXTRA_BASE_RESULT = + "android.credentials.ui.extra.BASE_RESULT"; + + /** User intentionally canceled the dialog. */ + public static final int RESULT_CODE_DIALOG_CANCELED = 0; + /** + * User made a selection and the dialog finished. The user selection result is in the + * {@code resultData}. + */ + public static final int RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION = 1; + /** + * The user has acknowledged the consent page rendered for when they first used Credential + * Manager on this device. + */ + public static final int RESULT_CODE_CREDENTIAL_MANAGER_CONSENT_ACKNOWLEDGED = 2; + /** + * The user has acknowledged the consent page rendered for enabling a new provider. + * This should only happen during the first time use. The provider info is in the + * {@code resultData}. + */ + public static final int RESULT_CODE_PROVIDER_ENABLED = 3; + /** + * The user has consented to switching to a new default provider. The provider info is in the + * {@code resultData}. + */ + public static final int RESULT_CODE_DEFAULT_PROVIDER_CHANGED = 4; + + @NonNull + private final IBinder mRequestToken; + + public BaseDialogResult(@NonNull IBinder requestToken) { + mRequestToken = requestToken; + } + + /** Returns the unique identifier for the request that launched the operation. */ + @NonNull + public IBinder getRequestToken() { + return mRequestToken; + } + + protected BaseDialogResult(@NonNull Parcel in) { + IBinder requestToken = in.readStrongBinder(); + mRequestToken = requestToken; + AnnotationValidations.validate(NonNull.class, null, mRequestToken); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeStrongBinder(mRequestToken); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator CREATOR = + new Creator() { + @Override + public BaseDialogResult createFromParcel(@NonNull Parcel in) { + return new BaseDialogResult(in); + } + + @Override + public BaseDialogResult[] newArray(int size) { + return new BaseDialogResult[size]; + } + }; +} diff --git a/core/java/android/credentials/ui/ProviderDialogResult.java b/core/java/android/credentials/ui/ProviderDialogResult.java new file mode 100644 index 000000000000..9d1be2063423 --- /dev/null +++ b/core/java/android/credentials/ui/ProviderDialogResult.java @@ -0,0 +1,100 @@ +/* + * 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.ui; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.AnnotationValidations; + +/** + * Result data matching {@link BaseDialogResult#RESULT_CODE_PROVIDER_ENABLED}, or {@link + * BaseDialogResult#RESULT_CODE_DEFAULT_PROVIDER_CHANGED}. + * + * @hide + */ +public class ProviderDialogResult extends BaseDialogResult implements Parcelable { + /** Parses and returns a ProviderDialogResult from the given resultData. */ + @Nullable + public static ProviderDialogResult fromResultData(@NonNull Bundle resultData) { + return resultData.getParcelable(EXTRA_PROVIDER_RESULT, ProviderDialogResult.class); + } + + /** + * Used for the UX to construct the {@code resultData Bundle} to send via the {@code + * ResultReceiver}. + */ + public static void addToBundle( + @NonNull ProviderDialogResult result, @NonNull Bundle bundle) { + bundle.putParcelable(EXTRA_PROVIDER_RESULT, result); + } + + /** + * The intent extra key for the {@code ProviderDialogResult} object when the credential + * selector activity finishes. + */ + private static final String EXTRA_PROVIDER_RESULT = + "android.credentials.ui.extra.PROVIDER_RESULT"; + + @NonNull + private final String mProviderId; + + public ProviderDialogResult(@NonNull IBinder requestToken, @NonNull String providerId) { + super(requestToken); + mProviderId = providerId; + } + + @NonNull + public String getProviderId() { + return mProviderId; + } + + protected ProviderDialogResult(@NonNull Parcel in) { + super(in); + String providerId = in.readString8(); + mProviderId = providerId; + AnnotationValidations.validate(NonNull.class, null, mProviderId); + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString8(mProviderId); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator CREATOR = + new Creator() { + @Override + public ProviderDialogResult createFromParcel(@NonNull Parcel in) { + return new ProviderDialogResult(in); + } + + @Override + public ProviderDialogResult[] newArray(int size) { + return new ProviderDialogResult[size]; + } + }; +} diff --git a/core/java/android/credentials/ui/UserSelectionDialogResult.java b/core/java/android/credentials/ui/UserSelectionDialogResult.java new file mode 100644 index 000000000000..eb3a4a8cfcbd --- /dev/null +++ b/core/java/android/credentials/ui/UserSelectionDialogResult.java @@ -0,0 +1,116 @@ +/* + * 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.ui; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.os.Bundle; +import android.os.IBinder; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.internal.util.AnnotationValidations; + +/** + * Result data matching {@link BaseDialogResult#RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION}. + * + * @hide + */ +public class UserSelectionDialogResult extends BaseDialogResult implements Parcelable { + /** Parses and returns a UserSelectionDialogResult from the given resultData. */ + @Nullable + public static UserSelectionDialogResult fromResultData(@NonNull Bundle resultData) { + return resultData.getParcelable( + EXTRA_USER_SELECTION_RESULT, UserSelectionDialogResult.class); + } + + /** + * Used for the UX to construct the {@code resultData Bundle} to send via the {@code + * ResultReceiver}. + */ + public static void addToBundle( + @NonNull UserSelectionDialogResult result, @NonNull Bundle bundle) { + bundle.putParcelable(EXTRA_USER_SELECTION_RESULT, result); + } + + /** + * The intent extra key for the {@code UserSelectionDialogResult} object when the credential + * selector activity finishes. + */ + private static final String EXTRA_USER_SELECTION_RESULT = + "android.credentials.ui.extra.USER_SELECTION_RESULT"; + + @NonNull + private final String mProviderId; + + // TODO: consider switching to string or other types, depending on the service implementation. + private final int mEntryId; + + public UserSelectionDialogResult( + @NonNull IBinder requestToken, @NonNull String providerId, + int entryId) { + super(requestToken); + mProviderId = providerId; + mEntryId = entryId; + } + + /** Returns provider package name whose entry was selected by the user. */ + @NonNull + public String getProviderId() { + return mProviderId; + } + + /** Returns the id of the visual entry that the user selected. */ + public int getEntryId() { + return mEntryId; + } + + protected UserSelectionDialogResult(@NonNull Parcel in) { + super(in); + String providerId = in.readString8(); + int entryId = in.readInt(); + + mProviderId = providerId; + AnnotationValidations.validate(NonNull.class, null, mProviderId); + mEntryId = entryId; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + super.writeToParcel(dest, flags); + dest.writeString8(mProviderId); + dest.writeInt(mEntryId); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator CREATOR = + new Creator() { + @Override + public UserSelectionDialogResult createFromParcel(@NonNull Parcel in) { + return new UserSelectionDialogResult(in); + } + + @Override + public UserSelectionDialogResult[] newArray(int size) { + return new UserSelectionDialogResult[size]; + } + }; +} diff --git a/core/java/android/credentials/ui/UserSelectionResult.java b/core/java/android/credentials/ui/UserSelectionResult.java deleted file mode 100644 index 2ac559381c6e..000000000000 --- a/core/java/android/credentials/ui/UserSelectionResult.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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.ui; - -import android.annotation.NonNull; -import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.internal.util.AnnotationValidations; - -/** - * User selection result information of a UX flow. - * - * Returned as part of the activity result intent data when the user dialog completes - * successfully. - * - * @hide - */ -public class UserSelectionResult implements Parcelable { - - /** - * The intent extra key for the {@code UserSelectionResult} object when the credential selector - * activity finishes. - */ - public static final String EXTRA_USER_SELECTION_RESULT = - "android.credentials.ui.extra.USER_SELECTION_RESULT"; - - @NonNull - private final IBinder mRequestToken; - - @NonNull - private final String mProviderId; - - // TODO: consider switching to string or other types, depending on the service implementation. - private final int mEntryId; - - public UserSelectionResult(@NonNull IBinder requestToken, @NonNull String providerId, - int entryId) { - mRequestToken = requestToken; - mProviderId = providerId; - mEntryId = entryId; - } - - /** Returns token of the app request that initiated this user dialog. */ - @NonNull - public IBinder getRequestToken() { - return mRequestToken; - } - - /** Returns provider package name whose entry was selected by the user. */ - @NonNull - public String getProviderId() { - return mProviderId; - } - - /** Returns the id of the visual entry that the user selected. */ - public int getEntryId() { - return mEntryId; - } - - protected UserSelectionResult(@NonNull Parcel in) { - IBinder requestToken = in.readStrongBinder(); - String providerId = in.readString8(); - int entryId = in.readInt(); - - mRequestToken = requestToken; - AnnotationValidations.validate(NonNull.class, null, mRequestToken); - mProviderId = providerId; - AnnotationValidations.validate(NonNull.class, null, mProviderId); - mEntryId = entryId; - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeStrongBinder(mRequestToken); - dest.writeString8(mProviderId); - dest.writeInt(mEntryId); - } - - @Override - public int describeContents() { - return 0; - } - - public static final @NonNull Creator CREATOR = - new Creator() { - @Override - public UserSelectionResult createFromParcel(@NonNull Parcel in) { - return new UserSelectionResult(in); - } - - @Override - public UserSelectionResult[] newArray(int size) { - return new UserSelectionResult[size]; - } - }; -} diff --git a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt index ec0c5b708abe..eac803afe3b0 100644 --- a/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt +++ b/packages/CredentialManager/src/com/android/credentialmanager/CredentialManagerRepo.kt @@ -16,7 +16,6 @@ package com.android.credentialmanager -import android.app.Activity import android.app.slice.Slice import android.app.slice.SliceSpec import android.content.Context @@ -25,7 +24,8 @@ import android.credentials.ui.Constants import android.credentials.ui.Entry import android.credentials.ui.ProviderData import android.credentials.ui.RequestInfo -import android.credentials.ui.UserSelectionResult +import android.credentials.ui.BaseDialogResult +import android.credentials.ui.UserSelectionDialogResult import android.graphics.drawable.Icon import android.os.Binder import android.os.Bundle @@ -67,21 +67,20 @@ class CredentialManagerRepo( } fun onCancel() { - resultReceiver?.send(Activity.RESULT_CANCELED, null) + val resultData = Bundle() + BaseDialogResult.addToBundle(BaseDialogResult(requestInfo.token), resultData) + resultReceiver?.send(BaseDialogResult.RESULT_CODE_DIALOG_CANCELED, resultData) } fun onOptionSelected(providerPackageName: String, entryId: Int) { - val userSelectionResult = UserSelectionResult( + val userSelectionDialogResult = UserSelectionDialogResult( requestInfo.token, providerPackageName, entryId ) val resultData = Bundle() - resultData.putParcelable( - UserSelectionResult.EXTRA_USER_SELECTION_RESULT, - userSelectionResult - ) - resultReceiver?.send(Activity.RESULT_OK, resultData) + UserSelectionDialogResult.addToBundle(userSelectionDialogResult, resultData) + resultReceiver?.send(BaseDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION, resultData) } fun getCredentialInitialUiState(): GetCredentialUiState { -- cgit v1.2.3-59-g8ed1b