Loading core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -39938,6 +39938,7 @@ package android.service.credentials { method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method public abstract void onClearCredentialState(@NonNull android.service.credentials.ClearCredentialStateRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>); field public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities"; field public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST = "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST"; field public static final String EXTRA_CREATE_CREDENTIAL_EXCEPTION = "android.service.credentials.extra.CREATE_CREDENTIAL_EXCEPTION"; field public static final String EXTRA_CREATE_CREDENTIAL_REQUEST = "android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST"; field public static final String EXTRA_CREATE_CREDENTIAL_RESPONSE = "android.service.credentials.extra.CREATE_CREDENTIAL_RESPONSE"; core/java/android/credentials/ui/Entry.java +1 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ public final class Entry implements Parcelable { /** Constructor to be used for an entry that requires a pending intent to be invoked * when clicked. */ // TODO: Remove this constructor as it is no longer used public Entry(@NonNull String key, @NonNull String subkey, @NonNull Slice slice, @NonNull PendingIntent pendingIntent, @NonNull Intent intent) { this(key, subkey, slice); Loading core/java/android/service/credentials/CredentialProviderService.java +27 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,33 @@ public abstract class CredentialProviderService extends Service { public static final String EXTRA_CREATE_CREDENTIAL_EXCEPTION = "android.service.credentials.extra.CREATE_CREDENTIAL_EXCEPTION"; /** * Intent extra: The {@link BeginGetCredentialRequest} attached with * the {@code pendingIntent} that is invoked when the user selects an * authentication entry (intending to unlock the provider app) on the UI. * * <p>When a provider app receives a {@link BeginGetCredentialRequest} through the * {@link CredentialProviderService#onBeginGetCredential} call, it can construct the * {@link BeginGetCredentialResponse} with either an authentication {@link Action} (if the app * is locked), or a {@link CredentialsResponseContent} (if the app is unlocked). In the former * case, i.e. the app is locked, user will be shown the authentication action. When selected, * the underlying {@link PendingIntent} will be invoked which will lead the user to provider's * unlock activity. This pending intent will also contain the original * {@link BeginGetCredentialRequest} to be retrieved and processed after the unlock * flow is complete. * * <p>After the app is unlocked, the {@link BeginGetCredentialResponse} must be constructed * using a {@link CredentialsResponseContent}, which must be set on an {@link Intent} as an * intent extra against CredentialProviderService#EXTRA_CREDENTIALS_RESPONSE_CONTENT}. * This intent should then be set as a result through {@link android.app.Activity#setResult} * before finishing the activity. * * <p> * Type: {@link BeginGetCredentialRequest} */ public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST = "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST"; private static final String TAG = "CredProviderService"; public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities"; Loading packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +8 −3 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL import com.android.credentialmanager.jetpack.provider.Action import com.android.credentialmanager.jetpack.provider.AuthenticationAction import com.android.credentialmanager.jetpack.provider.CredentialCountInformation import com.android.credentialmanager.jetpack.provider.CredentialEntry import com.android.credentialmanager.jetpack.provider.CreateEntry Loading Loading @@ -140,16 +141,20 @@ class GetFlowUtils { providerIcon: Drawable, authEntry: Entry?, ): AuthenticationEntryInfo? { // TODO: should also call fromSlice after getting the official jetpack code. if (authEntry == null) { return null } val authStructuredEntry = AuthenticationAction.fromSlice( authEntry!!.slice) if (authStructuredEntry == null) { return null } return AuthenticationEntryInfo( providerId = providerId, entryKey = authEntry.key, entrySubkey = authEntry.subkey, pendingIntent = authEntry.pendingIntent, pendingIntent = authStructuredEntry.pendingIntent, fillInIntent = authEntry.frameworkExtrasIntent, title = providerDisplayName, icon = providerIcon, Loading packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/AuthenticationAction.kt 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright (C) 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 com.android.credentialmanager.jetpack.provider import android.app.PendingIntent import android.app.slice.Slice import android.util.Log import androidx.annotation.VisibleForTesting /** * UI representation for a credential entry used during the get credential flow. * * TODO: move to jetpack. */ class AuthenticationAction constructor( val pendingIntent: PendingIntent ) { companion object { private const val TAG = "AuthenticationAction" @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal const val SLICE_HINT_PENDING_INTENT = "androidx.credentials.provider.authenticationAction.SLICE_HINT_PENDING_INTENT" @JvmStatic fun fromSlice(slice: Slice): AuthenticationAction? { slice.items.forEach { if (it.hasHint(SLICE_HINT_PENDING_INTENT)) { return try { AuthenticationAction(it.action) } catch (e: Exception) { Log.i(TAG, "fromSlice failed with: " + e.message) null } } } return null } } } Loading
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -39938,6 +39938,7 @@ package android.service.credentials { method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent); method public abstract void onClearCredentialState(@NonNull android.service.credentials.ClearCredentialStateRequest, @NonNull android.os.CancellationSignal, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>); field public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities"; field public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST = "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST"; field public static final String EXTRA_CREATE_CREDENTIAL_EXCEPTION = "android.service.credentials.extra.CREATE_CREDENTIAL_EXCEPTION"; field public static final String EXTRA_CREATE_CREDENTIAL_REQUEST = "android.service.credentials.extra.CREATE_CREDENTIAL_REQUEST"; field public static final String EXTRA_CREATE_CREDENTIAL_RESPONSE = "android.service.credentials.extra.CREATE_CREDENTIAL_RESPONSE";
core/java/android/credentials/ui/Entry.java +1 −0 Original line number Diff line number Diff line Loading @@ -88,6 +88,7 @@ public final class Entry implements Parcelable { /** Constructor to be used for an entry that requires a pending intent to be invoked * when clicked. */ // TODO: Remove this constructor as it is no longer used public Entry(@NonNull String key, @NonNull String subkey, @NonNull Slice slice, @NonNull PendingIntent pendingIntent, @NonNull Intent intent) { this(key, subkey, slice); Loading
core/java/android/service/credentials/CredentialProviderService.java +27 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,33 @@ public abstract class CredentialProviderService extends Service { public static final String EXTRA_CREATE_CREDENTIAL_EXCEPTION = "android.service.credentials.extra.CREATE_CREDENTIAL_EXCEPTION"; /** * Intent extra: The {@link BeginGetCredentialRequest} attached with * the {@code pendingIntent} that is invoked when the user selects an * authentication entry (intending to unlock the provider app) on the UI. * * <p>When a provider app receives a {@link BeginGetCredentialRequest} through the * {@link CredentialProviderService#onBeginGetCredential} call, it can construct the * {@link BeginGetCredentialResponse} with either an authentication {@link Action} (if the app * is locked), or a {@link CredentialsResponseContent} (if the app is unlocked). In the former * case, i.e. the app is locked, user will be shown the authentication action. When selected, * the underlying {@link PendingIntent} will be invoked which will lead the user to provider's * unlock activity. This pending intent will also contain the original * {@link BeginGetCredentialRequest} to be retrieved and processed after the unlock * flow is complete. * * <p>After the app is unlocked, the {@link BeginGetCredentialResponse} must be constructed * using a {@link CredentialsResponseContent}, which must be set on an {@link Intent} as an * intent extra against CredentialProviderService#EXTRA_CREDENTIALS_RESPONSE_CONTENT}. * This intent should then be set as a result through {@link android.app.Activity#setResult} * before finishing the activity. * * <p> * Type: {@link BeginGetCredentialRequest} */ public static final String EXTRA_BEGIN_GET_CREDENTIAL_REQUEST = "android.service.credentials.extra.BEGIN_GET_CREDENTIAL_REQUEST"; private static final String TAG = "CredProviderService"; public static final String CAPABILITY_META_DATA_KEY = "android.credentials.capabilities"; Loading
packages/CredentialManager/src/com/android/credentialmanager/DataConverter.kt +8 −3 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ import com.android.credentialmanager.jetpack.developer.CreatePasswordRequest import com.android.credentialmanager.jetpack.developer.CreatePublicKeyCredentialRequest import com.android.credentialmanager.jetpack.developer.PublicKeyCredential.Companion.TYPE_PUBLIC_KEY_CREDENTIAL import com.android.credentialmanager.jetpack.provider.Action import com.android.credentialmanager.jetpack.provider.AuthenticationAction import com.android.credentialmanager.jetpack.provider.CredentialCountInformation import com.android.credentialmanager.jetpack.provider.CredentialEntry import com.android.credentialmanager.jetpack.provider.CreateEntry Loading Loading @@ -140,16 +141,20 @@ class GetFlowUtils { providerIcon: Drawable, authEntry: Entry?, ): AuthenticationEntryInfo? { // TODO: should also call fromSlice after getting the official jetpack code. if (authEntry == null) { return null } val authStructuredEntry = AuthenticationAction.fromSlice( authEntry!!.slice) if (authStructuredEntry == null) { return null } return AuthenticationEntryInfo( providerId = providerId, entryKey = authEntry.key, entrySubkey = authEntry.subkey, pendingIntent = authEntry.pendingIntent, pendingIntent = authStructuredEntry.pendingIntent, fillInIntent = authEntry.frameworkExtrasIntent, title = providerDisplayName, icon = providerIcon, Loading
packages/CredentialManager/src/com/android/credentialmanager/jetpack/provider/AuthenticationAction.kt 0 → 100644 +55 −0 Original line number Diff line number Diff line /* * Copyright (C) 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 com.android.credentialmanager.jetpack.provider import android.app.PendingIntent import android.app.slice.Slice import android.util.Log import androidx.annotation.VisibleForTesting /** * UI representation for a credential entry used during the get credential flow. * * TODO: move to jetpack. */ class AuthenticationAction constructor( val pendingIntent: PendingIntent ) { companion object { private const val TAG = "AuthenticationAction" @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) internal const val SLICE_HINT_PENDING_INTENT = "androidx.credentials.provider.authenticationAction.SLICE_HINT_PENDING_INTENT" @JvmStatic fun fromSlice(slice: Slice): AuthenticationAction? { slice.items.forEach { if (it.hasHint(SLICE_HINT_PENDING_INTENT)) { return try { AuthenticationAction(it.action) } catch (e: Exception) { Log.i(TAG, "fromSlice failed with: " + e.message) null } } } return null } } }