diff options
11 files changed, 370 insertions, 84 deletions
diff --git a/core/java/android/credentials/selection/IntentCreationResult.java b/core/java/android/credentials/selection/IntentCreationResult.java new file mode 100644 index 000000000000..189ff7bbcb6e --- /dev/null +++ b/core/java/android/credentials/selection/IntentCreationResult.java @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2024 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.selection; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.Intent; + +/** + * Result of creating a Credential Manager UI intent. + * + * @hide + */ +public final class IntentCreationResult { + @NonNull + private final Intent mIntent; + @Nullable + private final String mFallbackUiPackageName; + @Nullable + private final String mOemUiPackageName; + @NonNull + private final OemUiUsageStatus mOemUiUsageStatus; + + private IntentCreationResult(@NonNull Intent intent, @Nullable String fallbackUiPackageName, + @Nullable String oemUiPackageName, OemUiUsageStatus oemUiUsageStatus) { + mIntent = intent; + mFallbackUiPackageName = fallbackUiPackageName; + mOemUiPackageName = oemUiPackageName; + mOemUiUsageStatus = oemUiUsageStatus; + } + + /** Returns the UI intent. */ + @NonNull + public Intent getIntent() { + return mIntent; + } + + /** + * Returns the result of attempting to use the config_oemCredentialManagerDialogComponent + * as the Credential Manager UI. + */ + @NonNull + public OemUiUsageStatus getOemUiUsageStatus() { + return mOemUiUsageStatus; + } + + /** + * Returns the package name of the ui component specified in + * config_fallbackCredentialManagerDialogComponent, or null if unspecified / not parsable + * successfully. + */ + @Nullable + public String getFallbackUiPackageName() { + return mFallbackUiPackageName; + } + + /** + * Returns the package name of the oem ui component specified in + * config_oemCredentialManagerDialogComponent, or null if unspecified / not parsable. + */ + @Nullable + public String getOemUiPackageName() { + return mOemUiPackageName; + } + + /** + * Result of attempting to use the config_oemCredentialManagerDialogComponent as the Credential + * Manager UI. + */ + public enum OemUiUsageStatus { + UNKNOWN, + // Success: the UI specified in config_oemCredentialManagerDialogComponent was used to + // fulfill the request. + SUCCESS, + // The config value was not specified (e.g. left empty). + OEM_UI_CONFIG_NOT_SPECIFIED, + // The config value component was specified but not found (e.g. component doesn't exist or + // component isn't a system app). + OEM_UI_CONFIG_SPECIFIED_BUT_NOT_FOUND, + // The config value component was found but not enabled. + OEM_UI_CONFIG_SPECIFIED_FOUND_BUT_NOT_ENABLED, + } + + /** + * Builder for {@link IntentCreationResult}. + * + * @hide + */ + public static final class Builder { + @NonNull + private Intent mIntent; + @Nullable + private String mFallbackUiPackageName = null; + @Nullable + private String mOemUiPackageName = null; + @NonNull + private OemUiUsageStatus mOemUiUsageStatus = OemUiUsageStatus.UNKNOWN; + + public Builder(Intent intent) { + mIntent = intent; + } + + /** + * Sets the package name of the ui component specified in + * config_fallbackCredentialManagerDialogComponent, or null if unspecified / not parsable + * successfully. + */ + @NonNull + public Builder setFallbackUiPackageName(@Nullable String fallbackUiPackageName) { + mFallbackUiPackageName = fallbackUiPackageName; + return this; + } + + /** + * Sets the package name of the oem ui component specified in + * config_oemCredentialManagerDialogComponent, or null if unspecified / not parsable. + */ + @NonNull + public Builder setOemUiPackageName(@Nullable String oemUiPackageName) { + mOemUiPackageName = oemUiPackageName; + return this; + } + + /** + * Sets the result of attempting to use the config_oemCredentialManagerDialogComponent + * as the Credential Manager UI. + */ + @NonNull + public Builder setOemUiUsageStatus(OemUiUsageStatus oemUiUsageStatus) { + mOemUiUsageStatus = oemUiUsageStatus; + return this; + } + + /** Builds a {@link IntentCreationResult}. */ + @NonNull + public IntentCreationResult build() { + return new IntentCreationResult(mIntent, mFallbackUiPackageName, mOemUiPackageName, + mOemUiUsageStatus); + } + } +} diff --git a/core/java/android/credentials/selection/IntentFactory.java b/core/java/android/credentials/selection/IntentFactory.java index 79fba9b19250..b98a0d825227 100644 --- a/core/java/android/credentials/selection/IntentFactory.java +++ b/core/java/android/credentials/selection/IntentFactory.java @@ -36,6 +36,8 @@ import android.os.ResultReceiver; import android.text.TextUtils; import android.util.Slog; +import com.android.internal.annotations.VisibleForTesting; + import java.util.ArrayList; /** @@ -57,22 +59,104 @@ public class IntentFactory { * @hide */ @NonNull - public static Intent createCredentialSelectorIntentForAutofill( + public static IntentCreationResult createCredentialSelectorIntentForAutofill( + @NonNull Context context, + @NonNull RequestInfo requestInfo, + @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling. + @NonNull + ArrayList<DisabledProviderData> disabledProviderDataList, + @NonNull ResultReceiver resultReceiver) { + return createCredentialSelectorIntentInternal(context, requestInfo, + disabledProviderDataList, resultReceiver); + } + + /** + * Generate a new launch intent to the Credential Selector UI. + * + * @param context the CredentialManager system service (only expected caller) + * context that may be used to query existence of the key UI + * application + * @param disabledProviderDataList the list of disabled provider data that when non-empty the + * UI should accordingly generate an entry suggesting the user + * to navigate to settings and enable them + * @param enabledProviderDataList the list of enabled provider that contain options for this + * request; the UI should render each option to the user for + * selection + * @param requestInfo the display information about the given app request + * @param resultReceiver used by the UI to send the UI selection result back + * @hide + */ + @NonNull + public static IntentCreationResult createCredentialSelectorIntentForCredMan( @NonNull Context context, @NonNull RequestInfo requestInfo, @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling. @NonNull + ArrayList<ProviderData> enabledProviderDataList, + @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling. + @NonNull ArrayList<DisabledProviderData> disabledProviderDataList, @NonNull ResultReceiver resultReceiver) { - return createCredentialSelectorIntent(context, requestInfo, + IntentCreationResult result = createCredentialSelectorIntentInternal(context, requestInfo, disabledProviderDataList, resultReceiver); + result.getIntent().putParcelableArrayListExtra( + ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, enabledProviderDataList); + return result; + } + + /** + * Generate a new launch intent to the Credential Selector UI. + * + * @param context the CredentialManager system service (only expected caller) + * context that may be used to query existence of the key UI + * application + * @param disabledProviderDataList the list of disabled provider data that when non-empty the + * UI should accordingly generate an entry suggesting the user + * to navigate to settings and enable them + * @param enabledProviderDataList the list of enabled provider that contain options for this + * request; the UI should render each option to the user for + * selection + * @param requestInfo the display information about the given app request + * @param resultReceiver used by the UI to send the UI selection result back + */ + @VisibleForTesting + @NonNull + public static Intent createCredentialSelectorIntent( + @NonNull Context context, + @NonNull RequestInfo requestInfo, + @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling. + @NonNull + ArrayList<ProviderData> enabledProviderDataList, + @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling. + @NonNull + ArrayList<DisabledProviderData> disabledProviderDataList, + @NonNull ResultReceiver resultReceiver) { + return createCredentialSelectorIntentForCredMan(context, requestInfo, + enabledProviderDataList, disabledProviderDataList, resultReceiver).getIntent(); + } + + /** + * Creates an Intent that cancels any UI matching the given request token id. + */ + @VisibleForTesting + @NonNull + public static Intent createCancelUiIntent(@NonNull Context context, + @NonNull IBinder requestToken, boolean shouldShowCancellationUi, + @NonNull String appPackageName) { + Intent intent = new Intent(); + IntentCreationResult.Builder intentResultBuilder = new IntentCreationResult.Builder(intent); + setCredentialSelectorUiComponentName(context, intent, intentResultBuilder); + intent.putExtra(CancelSelectionRequest.EXTRA_CANCEL_UI_REQUEST, + new CancelSelectionRequest(new RequestToken(requestToken), shouldShowCancellationUi, + appPackageName)); + return intent; } /** * Generate a new launch intent to the Credential Selector UI. */ @NonNull - private static Intent createCredentialSelectorIntent( + private static IntentCreationResult createCredentialSelectorIntentInternal( @NonNull Context context, @NonNull RequestInfo requestInfo, @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling. @@ -80,25 +164,37 @@ public class IntentFactory { ArrayList<DisabledProviderData> disabledProviderDataList, @NonNull ResultReceiver resultReceiver) { Intent intent = new Intent(); - setCredentialSelectorUiComponentName(context, intent); + IntentCreationResult.Builder intentResultBuilder = new IntentCreationResult.Builder(intent); + setCredentialSelectorUiComponentName(context, intent, intentResultBuilder); intent.putParcelableArrayListExtra( ProviderData.EXTRA_DISABLED_PROVIDER_DATA_LIST, disabledProviderDataList); intent.putExtra(RequestInfo.EXTRA_REQUEST_INFO, requestInfo); intent.putExtra( Constants.EXTRA_RESULT_RECEIVER, toIpcFriendlyResultReceiver(resultReceiver)); - - return intent; + return intentResultBuilder.build(); } private static void setCredentialSelectorUiComponentName(@NonNull Context context, - @NonNull Intent intent) { + @NonNull Intent intent, @NonNull IntentCreationResult.Builder intentResultBuilder) { if (configurableSelectorUiEnabled()) { - ComponentName componentName = getOemOverrideComponentName(context); + ComponentName componentName = getOemOverrideComponentName(context, intentResultBuilder); + + ComponentName fallbackUiComponentName = null; + try { + fallbackUiComponentName = ComponentName.unflattenFromString( + Resources.getSystem().getString( + com.android.internal.R.string + .config_fallbackCredentialManagerDialogComponent)); + intentResultBuilder.setFallbackUiPackageName( + fallbackUiComponentName.getPackageName()); + } catch (Exception e) { + Slog.w(TAG, "Fallback CredMan IU not found: " + e); + } + if (componentName == null) { - componentName = ComponentName.unflattenFromString(Resources.getSystem().getString( - com.android.internal.R.string - .config_fallbackCredentialManagerDialogComponent)); + componentName = fallbackUiComponentName; } + intent.setComponent(componentName); } else { ComponentName componentName = ComponentName.unflattenFromString(Resources.getSystem() @@ -113,7 +209,8 @@ public class IntentFactory { * default platform UI component name should be used instead. */ @Nullable - private static ComponentName getOemOverrideComponentName(@NonNull Context context) { + private static ComponentName getOemOverrideComponentName(@NonNull Context context, + @NonNull IntentCreationResult.Builder intentResultBuilder) { ComponentName result = null; String oemComponentString = Resources.getSystem() @@ -121,86 +218,54 @@ public class IntentFactory { com.android.internal.R.string .config_oemCredentialManagerDialogComponent); if (!TextUtils.isEmpty(oemComponentString)) { - ComponentName oemComponentName = ComponentName.unflattenFromString( - oemComponentString); + ComponentName oemComponentName = null; + try { + oemComponentName = ComponentName.unflattenFromString( + oemComponentString); + } catch (Exception e) { + Slog.i(TAG, "Failed to parse OEM component name " + oemComponentString + ": " + e); + } if (oemComponentName != null) { try { + intentResultBuilder.setOemUiPackageName(oemComponentName.getPackageName()); ActivityInfo info = context.getPackageManager().getActivityInfo( oemComponentName, PackageManager.ComponentInfoFlags.of( PackageManager.MATCH_SYSTEM_ONLY)); if (info.enabled && info.exported) { + intentResultBuilder.setOemUiUsageStatus(IntentCreationResult + .OemUiUsageStatus.SUCCESS); Slog.i(TAG, "Found enabled oem CredMan UI component." + oemComponentString); result = oemComponentName; } else { + intentResultBuilder.setOemUiUsageStatus(IntentCreationResult + .OemUiUsageStatus.OEM_UI_CONFIG_SPECIFIED_FOUND_BUT_NOT_ENABLED); Slog.i(TAG, "Found enabled oem CredMan UI component but it was not " + "enabled."); } } catch (PackageManager.NameNotFoundException e) { + intentResultBuilder.setOemUiUsageStatus(IntentCreationResult.OemUiUsageStatus + .OEM_UI_CONFIG_SPECIFIED_BUT_NOT_FOUND); Slog.i(TAG, "Unable to find oem CredMan UI component: " + oemComponentString + "."); } } else { + intentResultBuilder.setOemUiUsageStatus(IntentCreationResult.OemUiUsageStatus + .OEM_UI_CONFIG_SPECIFIED_BUT_NOT_FOUND); Slog.i(TAG, "Invalid OEM ComponentName format."); } } else { + intentResultBuilder.setOemUiUsageStatus( + IntentCreationResult.OemUiUsageStatus.OEM_UI_CONFIG_NOT_SPECIFIED); Slog.i(TAG, "Invalid empty OEM component name."); } return result; } /** - * Generate a new launch intent to the Credential Selector UI. - * - * @param context the CredentialManager system service (only expected caller) - * context that may be used to query existence of the key UI - * application - * @param disabledProviderDataList the list of disabled provider data that when non-empty the - * UI should accordingly generate an entry suggesting the user - * to navigate to settings and enable them - * @param enabledProviderDataList the list of enabled provider that contain options for this - * request; the UI should render each option to the user for - * selection - * @param requestInfo the display information about the given app request - * @param resultReceiver used by the UI to send the UI selection result back - */ - @NonNull - public static Intent createCredentialSelectorIntent( - @NonNull Context context, - @NonNull RequestInfo requestInfo, - @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling. - @NonNull - ArrayList<ProviderData> enabledProviderDataList, - @SuppressLint("ConcreteCollection") // Concrete collection needed for marshalling. - @NonNull - ArrayList<DisabledProviderData> disabledProviderDataList, - @NonNull ResultReceiver resultReceiver) { - Intent intent = createCredentialSelectorIntent(context, requestInfo, - disabledProviderDataList, resultReceiver); - intent.putParcelableArrayListExtra( - ProviderData.EXTRA_ENABLED_PROVIDER_DATA_LIST, enabledProviderDataList); - return intent; - } - - /** - * Creates an Intent that cancels any UI matching the given request token id. - */ - @NonNull - public static Intent createCancelUiIntent(@NonNull Context context, - @NonNull IBinder requestToken, boolean shouldShowCancellationUi, - @NonNull String appPackageName) { - Intent intent = new Intent(); - setCredentialSelectorUiComponentName(context, intent); - intent.putExtra(CancelSelectionRequest.EXTRA_CANCEL_UI_REQUEST, - new CancelSelectionRequest(new RequestToken(requestToken), shouldShowCancellationUi, - appPackageName)); - 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. */ diff --git a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java index 173cb36a1a34..cac42b17553a 100644 --- a/services/credentials/java/com/android/server/credentials/CreateRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/CreateRequestSession.java @@ -112,7 +112,8 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR Manifest.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS), /*defaultProviderId=*/flattenedPrimaryProviders, /*isShowAllOptionsRequested=*/ false), - providerDataList); + providerDataList, + mRequestSessionMetric); mClientCallback.onPendingIntent(mPendingIntent); } catch (RemoteException e) { mRequestSessionMetric.collectUiReturnedFinalPhase(/*uiReturned=*/ false); diff --git a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java index f5e1e41dbae4..24f66977ee90 100644 --- a/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java +++ b/services/credentials/java/com/android/server/credentials/CredentialManagerUi.java @@ -25,6 +25,7 @@ import android.content.Intent; import android.credentials.CredentialManager; import android.credentials.CredentialProviderInfo; import android.credentials.selection.DisabledProviderData; +import android.credentials.selection.IntentCreationResult; import android.credentials.selection.IntentFactory; import android.credentials.selection.ProviderData; import android.credentials.selection.RequestInfo; @@ -37,6 +38,8 @@ import android.os.ResultReceiver; import android.os.UserHandle; import android.service.credentials.CredentialProviderInfoFactory; +import com.android.server.credentials.metrics.RequestSessionMetric; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -159,7 +162,8 @@ public class CredentialManagerUi { * @param providerDataList the list of provider data from remote providers */ public PendingIntent createPendingIntent( - RequestInfo requestInfo, ArrayList<ProviderData> providerDataList) { + RequestInfo requestInfo, ArrayList<ProviderData> providerDataList, + RequestSessionMetric requestSessionMetric) { List<CredentialProviderInfo> allProviders = CredentialProviderInfoFactory.getCredentialProviderServices( mContext, @@ -174,10 +178,12 @@ public class CredentialManagerUi { .map(disabledProvider -> new DisabledProviderData( disabledProvider.getComponentName().flattenToString())).toList(); - Intent intent; - intent = IntentFactory.createCredentialSelectorIntent( - mContext, requestInfo, providerDataList, - new ArrayList<>(disabledProviderDataList), mResultReceiver); + IntentCreationResult intentCreationResult = IntentFactory + .createCredentialSelectorIntentForCredMan(mContext, requestInfo, providerDataList, + new ArrayList<>(disabledProviderDataList), mResultReceiver); + requestSessionMetric.collectUiConfigurationResults( + mContext, intentCreationResult, mUserId); + Intent intent = intentCreationResult.getIntent(); intent.setAction(UUID.randomUUID().toString()); //TODO: Create unique pending intent using request code and cancel any pre-existing pending // intents @@ -197,10 +203,15 @@ public class CredentialManagerUi { * of the pinned entry. * * @param requestInfo the information about the request + * @param requestSessionMetric the metric object for logging */ - public Intent createIntentForAutofill(RequestInfo requestInfo) { - return IntentFactory.createCredentialSelectorIntentForAutofill( - mContext, requestInfo, new ArrayList<>(), - mResultReceiver); + public Intent createIntentForAutofill(RequestInfo requestInfo, + RequestSessionMetric requestSessionMetric) { + IntentCreationResult intentCreationResult = IntentFactory + .createCredentialSelectorIntentForAutofill(mContext, requestInfo, new ArrayList<>(), + mResultReceiver); + requestSessionMetric.collectUiConfigurationResults( + mContext, intentCreationResult, mUserId); + return intentCreationResult.getIntent(); } } diff --git a/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java b/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java index eff53de75ff4..fd2a9a20640b 100644 --- a/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/GetCandidateRequestSession.java @@ -122,7 +122,8 @@ public class GetCandidateRequestSession extends RequestSession<GetCredentialRequ mRequestId, mClientRequest, mClientAppInfo.getPackageName(), PermissionUtils.hasPermission(mContext, mClientAppInfo.getPackageName(), Manifest.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS), - /*isShowAllOptionsRequested=*/ true)); + /*isShowAllOptionsRequested=*/ true), + mRequestSessionMetric); List<GetCredentialProviderData> candidateProviderDataList = new ArrayList<>(); for (ProviderData providerData : providerDataList) { diff --git a/services/credentials/java/com/android/server/credentials/GetRequestSession.java b/services/credentials/java/com/android/server/credentials/GetRequestSession.java index 6513ae1af369..d55d8effd381 100644 --- a/services/credentials/java/com/android/server/credentials/GetRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/GetRequestSession.java @@ -111,7 +111,8 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest, Manifest.permission .CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS), /*isShowAllOptionsRequested=*/ false), - providerDataList); + providerDataList, + mRequestSessionMetric); mClientCallback.onPendingIntent(mPendingIntent); } catch (RemoteException e) { mRequestSessionMetric.collectUiReturnedFinalPhase(/*uiReturned=*/ false); diff --git a/services/credentials/java/com/android/server/credentials/MetricUtilities.java b/services/credentials/java/com/android/server/credentials/MetricUtilities.java index bdea4f9d2baa..16bf17781eea 100644 --- a/services/credentials/java/com/android/server/credentials/MetricUtilities.java +++ b/services/credentials/java/com/android/server/credentials/MetricUtilities.java @@ -16,6 +16,7 @@ package com.android.server.credentials; +import android.annotation.UserIdInt; import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; @@ -68,17 +69,27 @@ public class MetricUtilities { * * @return the uid of a given package */ - protected static int getPackageUid(Context context, ComponentName componentName) { - int sessUid = -1; + protected static int getPackageUid(Context context, ComponentName componentName, + @UserIdInt int userId) { + if (componentName == null) { + return -1; + } + return getPackageUid(context, componentName.getPackageName(), userId); + } + + /** Returns the package uid, or -1 if not found. */ + public static int getPackageUid(Context context, String packageName, + @UserIdInt int userId) { + if (packageName == null) { + return -1; + } try { - // Only for T and above, which is fine for our use case - sessUid = context.getPackageManager().getApplicationInfo( - componentName.getPackageName(), - PackageManager.ApplicationInfoFlags.of(0)).uid; + return context.getPackageManager().getPackageUidAsUser(packageName, + PackageManager.PackageInfoFlags.of(0), userId); } catch (Throwable t) { - Slog.i(TAG, "Couldn't find required uid"); + Slog.i(TAG, "Couldn't find uid for " + packageName + ": " + t); + return -1; } - return sessUid; } /** diff --git a/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java b/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java index 6e8f7c8d7722..e4b5c776301e 100644 --- a/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java +++ b/services/credentials/java/com/android/server/credentials/PrepareGetRequestSession.java @@ -193,7 +193,8 @@ public class PrepareGetRequestSession extends GetRequestSession { PermissionUtils.hasPermission(mContext, mClientAppInfo.getPackageName(), Manifest.permission.CREDENTIAL_MANAGER_SET_ALLOWED_PROVIDERS), /*isShowAllOptionsRequested=*/ false), - providerDataList); + providerDataList, + mRequestSessionMetric); } else { return null; } diff --git a/services/credentials/java/com/android/server/credentials/ProviderSession.java b/services/credentials/java/com/android/server/credentials/ProviderSession.java index c16e2327abfb..dfc08f04386e 100644 --- a/services/credentials/java/com/android/server/credentials/ProviderSession.java +++ b/services/credentials/java/com/android/server/credentials/ProviderSession.java @@ -153,7 +153,7 @@ public abstract class ProviderSession<T, R> mUserId = userId; mComponentName = componentName; mRemoteCredentialService = remoteCredentialService; - mProviderSessionUid = MetricUtilities.getPackageUid(mContext, mComponentName); + mProviderSessionUid = MetricUtilities.getPackageUid(mContext, mComponentName, userId); mProviderSessionMetric = new ProviderSessionMetric( ((RequestSession) mCallbacks).mRequestSessionMetric.getSessionIdTrackTwo()); } diff --git a/services/credentials/java/com/android/server/credentials/metrics/OemUiUsageStatus.java b/services/credentials/java/com/android/server/credentials/metrics/OemUiUsageStatus.java index 2fd3a868369d..80ce354c4972 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/OemUiUsageStatus.java +++ b/services/credentials/java/com/android/server/credentials/metrics/OemUiUsageStatus.java @@ -22,7 +22,12 @@ import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_FIN import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_FINAL_NO_UID_REPORTED__OEM_UI_USAGE_STATUS__OEM_UI_USAGE_STATUS_SPECIFIED_BUT_NOT_FOUND; import static com.android.internal.util.FrameworkStatsLog.CREDENTIAL_MANAGER_FINAL_NO_UID_REPORTED__OEM_UI_USAGE_STATUS__OEM_UI_USAGE_STATUS_SPECIFIED_BUT_NOT_ENABLED; +import android.credentials.selection.IntentCreationResult; +/** + * Result of attempting to use the config_oemCredentialManagerDialogComponent as the Credential + * Manager UI. + */ public enum OemUiUsageStatus { UNKNOWN(CREDENTIAL_MANAGER_FINAL_NO_UID_REPORTED__OEM_UI_USAGE_STATUS__OEM_UI_USAGE_STATUS_UNKNOWN), SUCCESS(CREDENTIAL_MANAGER_FINAL_NO_UID_REPORTED__OEM_UI_USAGE_STATUS__OEM_UI_USAGE_STATUS_SUCCESS), @@ -39,4 +44,21 @@ public enum OemUiUsageStatus { public int getLoggingInt() { return mLoggingInt; } + + /** Factory method. */ + public static OemUiUsageStatus createFrom(IntentCreationResult.OemUiUsageStatus from) { + switch (from) { + case UNKNOWN: + return OemUiUsageStatus.UNKNOWN; + case SUCCESS: + return OemUiUsageStatus.SUCCESS; + case OEM_UI_CONFIG_NOT_SPECIFIED: + return OemUiUsageStatus.FAILURE_NOT_SPECIFIED; + case OEM_UI_CONFIG_SPECIFIED_BUT_NOT_FOUND: + return OemUiUsageStatus.FAILURE_SPECIFIED_BUT_NOT_FOUND; + case OEM_UI_CONFIG_SPECIFIED_FOUND_BUT_NOT_ENABLED: + return OemUiUsageStatus.FAILURE_SPECIFIED_BUT_NOT_ENABLED; + } + return OemUiUsageStatus.UNKNOWN; + } } diff --git a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java index a77bd3e280dd..619a56846e95 100644 --- a/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java +++ b/services/credentials/java/com/android/server/credentials/metrics/RequestSessionMetric.java @@ -30,9 +30,12 @@ import static com.android.server.credentials.metrics.ApiName.GET_CREDENTIAL; import static com.android.server.credentials.metrics.ApiName.GET_CREDENTIAL_VIA_REGISTRY; import android.annotation.NonNull; +import android.annotation.UserIdInt; import android.content.ComponentName; +import android.content.Context; import android.credentials.CreateCredentialRequest; import android.credentials.GetCredentialRequest; +import android.credentials.selection.IntentCreationResult; import android.credentials.selection.UserSelectionDialogResult; import android.util.Slog; @@ -270,6 +273,21 @@ public class RequestSessionMetric { } } + /** Log results of the device Credential Manager UI configuration. */ + public void collectUiConfigurationResults(Context context, IntentCreationResult result, + @UserIdInt int userId) { + try { + mChosenProviderFinalPhaseMetric.setOemUiUid(MetricUtilities.getPackageUid( + context, result.getOemUiPackageName(), userId)); + mChosenProviderFinalPhaseMetric.setFallbackUiUid(MetricUtilities.getPackageUid( + context, result.getFallbackUiPackageName(), userId)); + mChosenProviderFinalPhaseMetric.setOemUiUsageStatus( + OemUiUsageStatus.createFrom(result.getOemUiUsageStatus())); + } catch (Exception e) { + Slog.w(TAG, "Unexpected error during ui configuration result collection: " + e); + } + } + /** * Allows encapsulating the overall final phase metric status from the chosen and final * provider. |