Loading core/java/android/service/autofill/AutofillService.java +8 −0 Original line number Diff line number Diff line Loading @@ -600,6 +600,14 @@ public abstract class AutofillService extends Service { */ public static final String EXTRA_ERROR = "error"; /** * Name of the key used to mark whether the fill response is for a webview. * * @hide */ public static final String WEBVIEW_REQUESTED_CREDENTIAL_KEY = "webview_requested_credential"; private final IAutoFillService mInterface = new IAutoFillService.Stub() { @Override public void onConnectedStateChanged(boolean connected) { Loading packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt +23 −11 Original line number Diff line number Diff line Loading @@ -116,8 +116,10 @@ class CredentialAutofillService : AutofillService() { return } val responseClientState = Bundle() responseClientState.putBoolean(WEBVIEW_REQUESTED_CREDENTIAL_KEY, false) val getCredRequest: GetCredentialRequest? = getCredManRequest(structure, sessionId, requestId) requestId, responseClientState) if (getCredRequest == null) { Log.i(TAG, "No credential manager request found") callback.onFailure("No credential manager request found") Loading Loading @@ -153,7 +155,8 @@ class CredentialAutofillService : AutofillService() { return } val fillResponse = convertToFillResponse(result, request) val fillResponse = convertToFillResponse(result, request, responseClientState) if (fillResponse != null) { callback.onSuccess(fillResponse) } else { Loading Loading @@ -260,7 +263,8 @@ class CredentialAutofillService : AutofillService() { private fun convertToFillResponse( getCredResponse: GetCandidateCredentialsResponse, filLRequest: FillRequest filLRequest: FillRequest, responseClientState: Bundle ): FillResponse? { val candidateProviders = getCredResponse.candidateProviderDataList if (candidateProviders.isEmpty()) { Loading @@ -281,6 +285,7 @@ class CredentialAutofillService : AutofillService() { if (!validFillResponse) { return null } fillResponseBuilder.setClientState(responseClientState) return fillResponseBuilder.build() } Loading Loading @@ -578,10 +583,11 @@ class CredentialAutofillService : AutofillService() { private fun getCredManRequest( structure: AssistStructure, sessionId: Int, requestId: Int requestId: Int, responseClientState: Bundle ): GetCredentialRequest? { val credentialOptions: MutableList<CredentialOption> = mutableListOf() traverseStructure(structure, credentialOptions) traverseStructure(structure, credentialOptions, responseClientState) if (credentialOptions.isNotEmpty()) { val dataBundle = Bundle() Loading @@ -596,7 +602,8 @@ class CredentialAutofillService : AutofillService() { private fun traverseStructure( structure: AssistStructure, cmRequests: MutableList<CredentialOption> cmRequests: MutableList<CredentialOption>, responseClientState: Bundle ) { val windowNodes: List<AssistStructure.WindowNode> = structure.run { Loading @@ -604,16 +611,17 @@ class CredentialAutofillService : AutofillService() { } windowNodes.forEach { windowNode: AssistStructure.WindowNode -> traverseNode(windowNode.rootViewNode, cmRequests) traverseNode(windowNode.rootViewNode, cmRequests, responseClientState) } } private fun traverseNode( viewNode: AssistStructure.ViewNode, cmRequests: MutableList<CredentialOption> cmRequests: MutableList<CredentialOption>, responseClientState: Bundle ) { viewNode.autofillId?.let { val options = getCredentialOptionsFromViewNode(viewNode, it) val options = getCredentialOptionsFromViewNode(viewNode, it, responseClientState) cmRequests.addAll(options) } Loading @@ -623,13 +631,14 @@ class CredentialAutofillService : AutofillService() { } children.forEach { childNode: AssistStructure.ViewNode -> traverseNode(childNode, cmRequests) traverseNode(childNode, cmRequests, responseClientState) } } private fun getCredentialOptionsFromViewNode( viewNode: AssistStructure.ViewNode, autofillId: AutofillId autofillId: AutofillId, responseClientState: Bundle ): List<CredentialOption> { // TODO(b/293945193) Replace with isCredential check from viewNode val credentialHints: MutableList<String> = mutableListOf() Loading @@ -637,6 +646,9 @@ class CredentialAutofillService : AutofillService() { for (hint in viewNode.autofillHints!!) { if (hint.startsWith(CRED_HINT_PREFIX)) { credentialHints.add(hint.substringAfter(CRED_HINT_PREFIX)) if (viewNode.webDomain != null) { responseClientState.putBoolean(WEBVIEW_REQUESTED_CREDENTIAL_KEY, true) } } } } Loading services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java +13 −2 Original line number Diff line number Diff line Loading @@ -254,6 +254,14 @@ public final class PresentationStatsEventLogger { mEventInternal.ifPresent(event -> event.mIsCredentialRequest = isCredentialRequest); } /** * Set webview_requested_credential */ public void maybeSetWebviewRequestedCredential(boolean webviewRequestedCredential) { mEventInternal.ifPresent(event -> event.mWebviewRequestedCredential = webviewRequestedCredential); } public void maybeSetNoPresentationEventReason(@NotShownReason int reason) { mEventInternal.ifPresent(event -> { if (event.mCountShown == 0) { Loading Loading @@ -578,7 +586,8 @@ public final class PresentationStatsEventLogger { + " mDetectionPreference=" + event.mDetectionPreference + " mFieldClassificationRequestId=" + event.mFieldClassificationRequestId + " mAppPackageUid=" + mCallingAppUid + " mIsCredentialRequest=" + event.mIsCredentialRequest); + " mIsCredentialRequest=" + event.mIsCredentialRequest + " mWebviewRequestedCredential=" + event.mWebviewRequestedCredential); } // TODO(b/234185326): Distinguish empty responses from other no presentation reasons. Loading Loading @@ -618,7 +627,8 @@ public final class PresentationStatsEventLogger { event.mDetectionPreference, event.mFieldClassificationRequestId, mCallingAppUid, event.mIsCredentialRequest); event.mIsCredentialRequest, event.mWebviewRequestedCredential); mEventInternal = Optional.empty(); } Loading Loading @@ -653,6 +663,7 @@ public final class PresentationStatsEventLogger { @DetectionPreference int mDetectionPreference = DETECTION_PREFER_UNKNOWN; int mFieldClassificationRequestId = -1; boolean mIsCredentialRequest = false; boolean mWebviewRequestedCredential = false; PresentationStatsEventInternal() {} } Loading services/autofill/java/com/android/server/autofill/Session.java +4 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.autofill; import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES; import static android.service.autofill.AutofillService.EXTRA_FILL_RESPONSE; import static android.service.autofill.AutofillService.WEBVIEW_REQUESTED_CREDENTIAL_KEY; import static android.service.autofill.Dataset.PICK_REASON_NO_PCC; import static android.service.autofill.Dataset.PICK_REASON_PCC_DETECTION_ONLY; import static android.service.autofill.Dataset.PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER; Loading Loading @@ -5516,8 +5517,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mResponses.put(requestId, newResponse); mClientState = newClientState != null ? newClientState : newResponse.getClientState(); boolean webviewRequestedCredman = newClientState != null && newClientState.getBoolean( WEBVIEW_REQUESTED_CREDENTIAL_KEY, false); List<Dataset> datasetList = newResponse.getDatasets(); mPresentationStatsEventLogger.maybeSetWebviewRequestedCredential(webviewRequestedCredman); mPresentationStatsEventLogger.maybeSetFieldClassificationRequestId(sIdCounterForPcc.get()); mPresentationStatsEventLogger.maybeSetAvailableCount(datasetList, mCurrentViewId); mFillResponseEventLogger.maybeSetDatasetsCountAfterPotentialPccFiltering(datasetList); Loading Loading
core/java/android/service/autofill/AutofillService.java +8 −0 Original line number Diff line number Diff line Loading @@ -600,6 +600,14 @@ public abstract class AutofillService extends Service { */ public static final String EXTRA_ERROR = "error"; /** * Name of the key used to mark whether the fill response is for a webview. * * @hide */ public static final String WEBVIEW_REQUESTED_CREDENTIAL_KEY = "webview_requested_credential"; private final IAutoFillService mInterface = new IAutoFillService.Stub() { @Override public void onConnectedStateChanged(boolean connected) { Loading
packages/CredentialManager/src/com/android/credentialmanager/autofill/CredentialAutofillService.kt +23 −11 Original line number Diff line number Diff line Loading @@ -116,8 +116,10 @@ class CredentialAutofillService : AutofillService() { return } val responseClientState = Bundle() responseClientState.putBoolean(WEBVIEW_REQUESTED_CREDENTIAL_KEY, false) val getCredRequest: GetCredentialRequest? = getCredManRequest(structure, sessionId, requestId) requestId, responseClientState) if (getCredRequest == null) { Log.i(TAG, "No credential manager request found") callback.onFailure("No credential manager request found") Loading Loading @@ -153,7 +155,8 @@ class CredentialAutofillService : AutofillService() { return } val fillResponse = convertToFillResponse(result, request) val fillResponse = convertToFillResponse(result, request, responseClientState) if (fillResponse != null) { callback.onSuccess(fillResponse) } else { Loading Loading @@ -260,7 +263,8 @@ class CredentialAutofillService : AutofillService() { private fun convertToFillResponse( getCredResponse: GetCandidateCredentialsResponse, filLRequest: FillRequest filLRequest: FillRequest, responseClientState: Bundle ): FillResponse? { val candidateProviders = getCredResponse.candidateProviderDataList if (candidateProviders.isEmpty()) { Loading @@ -281,6 +285,7 @@ class CredentialAutofillService : AutofillService() { if (!validFillResponse) { return null } fillResponseBuilder.setClientState(responseClientState) return fillResponseBuilder.build() } Loading Loading @@ -578,10 +583,11 @@ class CredentialAutofillService : AutofillService() { private fun getCredManRequest( structure: AssistStructure, sessionId: Int, requestId: Int requestId: Int, responseClientState: Bundle ): GetCredentialRequest? { val credentialOptions: MutableList<CredentialOption> = mutableListOf() traverseStructure(structure, credentialOptions) traverseStructure(structure, credentialOptions, responseClientState) if (credentialOptions.isNotEmpty()) { val dataBundle = Bundle() Loading @@ -596,7 +602,8 @@ class CredentialAutofillService : AutofillService() { private fun traverseStructure( structure: AssistStructure, cmRequests: MutableList<CredentialOption> cmRequests: MutableList<CredentialOption>, responseClientState: Bundle ) { val windowNodes: List<AssistStructure.WindowNode> = structure.run { Loading @@ -604,16 +611,17 @@ class CredentialAutofillService : AutofillService() { } windowNodes.forEach { windowNode: AssistStructure.WindowNode -> traverseNode(windowNode.rootViewNode, cmRequests) traverseNode(windowNode.rootViewNode, cmRequests, responseClientState) } } private fun traverseNode( viewNode: AssistStructure.ViewNode, cmRequests: MutableList<CredentialOption> cmRequests: MutableList<CredentialOption>, responseClientState: Bundle ) { viewNode.autofillId?.let { val options = getCredentialOptionsFromViewNode(viewNode, it) val options = getCredentialOptionsFromViewNode(viewNode, it, responseClientState) cmRequests.addAll(options) } Loading @@ -623,13 +631,14 @@ class CredentialAutofillService : AutofillService() { } children.forEach { childNode: AssistStructure.ViewNode -> traverseNode(childNode, cmRequests) traverseNode(childNode, cmRequests, responseClientState) } } private fun getCredentialOptionsFromViewNode( viewNode: AssistStructure.ViewNode, autofillId: AutofillId autofillId: AutofillId, responseClientState: Bundle ): List<CredentialOption> { // TODO(b/293945193) Replace with isCredential check from viewNode val credentialHints: MutableList<String> = mutableListOf() Loading @@ -637,6 +646,9 @@ class CredentialAutofillService : AutofillService() { for (hint in viewNode.autofillHints!!) { if (hint.startsWith(CRED_HINT_PREFIX)) { credentialHints.add(hint.substringAfter(CRED_HINT_PREFIX)) if (viewNode.webDomain != null) { responseClientState.putBoolean(WEBVIEW_REQUESTED_CREDENTIAL_KEY, true) } } } } Loading
services/autofill/java/com/android/server/autofill/PresentationStatsEventLogger.java +13 −2 Original line number Diff line number Diff line Loading @@ -254,6 +254,14 @@ public final class PresentationStatsEventLogger { mEventInternal.ifPresent(event -> event.mIsCredentialRequest = isCredentialRequest); } /** * Set webview_requested_credential */ public void maybeSetWebviewRequestedCredential(boolean webviewRequestedCredential) { mEventInternal.ifPresent(event -> event.mWebviewRequestedCredential = webviewRequestedCredential); } public void maybeSetNoPresentationEventReason(@NotShownReason int reason) { mEventInternal.ifPresent(event -> { if (event.mCountShown == 0) { Loading Loading @@ -578,7 +586,8 @@ public final class PresentationStatsEventLogger { + " mDetectionPreference=" + event.mDetectionPreference + " mFieldClassificationRequestId=" + event.mFieldClassificationRequestId + " mAppPackageUid=" + mCallingAppUid + " mIsCredentialRequest=" + event.mIsCredentialRequest); + " mIsCredentialRequest=" + event.mIsCredentialRequest + " mWebviewRequestedCredential=" + event.mWebviewRequestedCredential); } // TODO(b/234185326): Distinguish empty responses from other no presentation reasons. Loading Loading @@ -618,7 +627,8 @@ public final class PresentationStatsEventLogger { event.mDetectionPreference, event.mFieldClassificationRequestId, mCallingAppUid, event.mIsCredentialRequest); event.mIsCredentialRequest, event.mWebviewRequestedCredential); mEventInternal = Optional.empty(); } Loading Loading @@ -653,6 +663,7 @@ public final class PresentationStatsEventLogger { @DetectionPreference int mDetectionPreference = DETECTION_PREFER_UNKNOWN; int mFieldClassificationRequestId = -1; boolean mIsCredentialRequest = false; boolean mWebviewRequestedCredential = false; PresentationStatsEventInternal() {} } Loading
services/autofill/java/com/android/server/autofill/Session.java +4 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server.autofill; import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES; import static android.service.autofill.AutofillService.EXTRA_FILL_RESPONSE; import static android.service.autofill.AutofillService.WEBVIEW_REQUESTED_CREDENTIAL_KEY; import static android.service.autofill.Dataset.PICK_REASON_NO_PCC; import static android.service.autofill.Dataset.PICK_REASON_PCC_DETECTION_ONLY; import static android.service.autofill.Dataset.PICK_REASON_PCC_DETECTION_PREFERRED_WITH_PROVIDER; Loading Loading @@ -5516,8 +5517,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState mResponses.put(requestId, newResponse); mClientState = newClientState != null ? newClientState : newResponse.getClientState(); boolean webviewRequestedCredman = newClientState != null && newClientState.getBoolean( WEBVIEW_REQUESTED_CREDENTIAL_KEY, false); List<Dataset> datasetList = newResponse.getDatasets(); mPresentationStatsEventLogger.maybeSetWebviewRequestedCredential(webviewRequestedCredman); mPresentationStatsEventLogger.maybeSetFieldClassificationRequestId(sIdCounterForPcc.get()); mPresentationStatsEventLogger.maybeSetAvailableCount(datasetList, mCurrentViewId); mFillResponseEventLogger.maybeSetDatasetsCountAfterPotentialPccFiltering(datasetList); Loading