Move CredentialProviderInfo for test/settings (framework)
This is a precusor CL to adding a subtitle for settings
to use so we need to move CPI where it can be used
by settings, atest and CTS.
Test: ondevice & atest & cts
Bug: 253157366
Change-Id: I2ffb1f89caf3f2c5bbf7d4dd693ad9a1bbc93fbb
(cherry picked from commit on googleplex-android-review.googlesource.com host: 496d3a3aae)
Merged-In: I2ffb1f89caf3f2c5bbf7d4dd693ad9a1bbc93fbb
This commit is contained in:
committed by
Cherrypicker Worker
parent
9397e3117e
commit
8d08ee778a
@@ -1072,6 +1072,40 @@ package android.content.rollback {
|
||||
|
||||
}
|
||||
|
||||
package android.credentials {
|
||||
|
||||
public final class CredentialManager {
|
||||
method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.QUERY_ALL_PACKAGES, "android.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS"}) public java.util.List<android.credentials.CredentialProviderInfo> getCredentialProviderServicesForTesting(int);
|
||||
method public static boolean isServiceEnabled(@NonNull android.content.Context);
|
||||
field public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0; // 0x0
|
||||
field public static final int PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY = 1; // 0x1
|
||||
field public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2; // 0x2
|
||||
}
|
||||
|
||||
public final class CredentialProviderInfo implements android.os.Parcelable {
|
||||
method public int describeContents();
|
||||
method @NonNull public java.util.List<java.lang.String> getCapabilities();
|
||||
method @NonNull public android.content.ComponentName getComponentName();
|
||||
method @Nullable public CharSequence getLabel(@NonNull android.content.Context);
|
||||
method @Nullable public android.graphics.drawable.Drawable getServiceIcon(@NonNull android.content.Context);
|
||||
method @NonNull public android.content.pm.ServiceInfo getServiceInfo();
|
||||
method @NonNull public boolean hasCapability(@NonNull String);
|
||||
method public boolean isEnabled();
|
||||
method public boolean isSystemProvider();
|
||||
method public void writeToParcel(@NonNull android.os.Parcel, int);
|
||||
field @NonNull public static final android.os.Parcelable.Creator<android.credentials.CredentialProviderInfo> CREATOR;
|
||||
}
|
||||
|
||||
public static final class CredentialProviderInfo.Builder {
|
||||
ctor public CredentialProviderInfo.Builder(@NonNull android.content.pm.ServiceInfo);
|
||||
method @NonNull public android.credentials.CredentialProviderInfo.Builder addCapabilities(@NonNull java.util.List<java.lang.String>);
|
||||
method @NonNull public android.credentials.CredentialProviderInfo build();
|
||||
method @NonNull public android.credentials.CredentialProviderInfo.Builder setEnabled(boolean);
|
||||
method @NonNull public android.credentials.CredentialProviderInfo.Builder setSystemProvider(boolean);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.credentials.ui {
|
||||
|
||||
public final class AuthenticationEntry implements android.os.Parcelable {
|
||||
|
||||
@@ -26,12 +26,12 @@ import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemService;
|
||||
import android.annotation.TestApi;
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.IntentSender;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.OutcomeReceiver;
|
||||
@@ -75,21 +75,21 @@ public final class CredentialManager {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0;
|
||||
@TestApi public static final int PROVIDER_FILTER_ALL_PROVIDERS = 0;
|
||||
|
||||
/**
|
||||
* Returns system credential providers only.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY = 1;
|
||||
@TestApi public static final int PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY = 1;
|
||||
|
||||
/**
|
||||
* Returns user credential providers only.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2;
|
||||
@TestApi public static final int PROVIDER_FILTER_USER_PROVIDERS_ONLY = 2;
|
||||
|
||||
private final Context mContext;
|
||||
private final ICredentialManager mService;
|
||||
@@ -262,44 +262,6 @@ public final class CredentialManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of all user configurable credential providers registered on the system. This API
|
||||
* is intended for browsers and settings apps.
|
||||
*
|
||||
* @param cancellationSignal an optional signal that allows for cancelling this call
|
||||
* @param executor the callback will take place on this {@link Executor}
|
||||
* @param callback the callback invoked when the request succeeds or fails
|
||||
* @hide
|
||||
*/
|
||||
@RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
|
||||
public void listEnabledProviders(
|
||||
@Nullable CancellationSignal cancellationSignal,
|
||||
@CallbackExecutor @NonNull Executor executor,
|
||||
@NonNull
|
||||
OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
|
||||
callback) {
|
||||
requireNonNull(executor, "executor must not be null");
|
||||
requireNonNull(callback, "callback must not be null");
|
||||
|
||||
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
|
||||
Log.w(TAG, "listEnabledProviders already canceled");
|
||||
return;
|
||||
}
|
||||
|
||||
ICancellationSignal cancelRemote = null;
|
||||
try {
|
||||
cancelRemote =
|
||||
mService.listEnabledProviders(
|
||||
new ListEnabledProvidersTransport(executor, callback));
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
if (cancellationSignal != null && cancelRemote != null) {
|
||||
cancellationSignal.setRemote(cancelRemote);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of all user configurable credential providers registered on the system. This API
|
||||
* is intended for settings apps.
|
||||
@@ -348,36 +310,43 @@ public final class CredentialManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of ServiceInfo for all discovered credential providers on this device.
|
||||
* Returns the list of CredentialProviderInfo for all discovered credential providers on this
|
||||
* device but will include test system providers as well.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)
|
||||
public List<ServiceInfo> getCredentialProviderServicesForTesting(
|
||||
@ProviderFilter int providerFilter) {
|
||||
@TestApi
|
||||
@RequiresPermission(
|
||||
anyOf = {
|
||||
android.Manifest.permission.QUERY_ALL_PACKAGES,
|
||||
android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS
|
||||
})
|
||||
public List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
|
||||
@ProviderFilter int providerFilter) {
|
||||
try {
|
||||
return mService.getCredentialProviderServices(
|
||||
mContext.getUserId(),
|
||||
/* disableSystemAppVerificationForTests= */ true,
|
||||
providerFilter);
|
||||
return mService.getCredentialProviderServicesForTesting(providerFilter);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of ServiceInfo for all discovered credential providers on this device.
|
||||
* Returns the list of CredentialProviderInfo for all discovered credential providers on this
|
||||
* device.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
@RequiresPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)
|
||||
public List<ServiceInfo> getCredentialProviderServices(
|
||||
@RequiresPermission(
|
||||
anyOf = {
|
||||
android.Manifest.permission.QUERY_ALL_PACKAGES,
|
||||
android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS
|
||||
})
|
||||
public List<CredentialProviderInfo> getCredentialProviderServices(
|
||||
int userId, @ProviderFilter int providerFilter) {
|
||||
try {
|
||||
return mService.getCredentialProviderServices(
|
||||
userId, /* disableSystemAppVerificationForTests= */ false, providerFilter);
|
||||
return mService.getCredentialProviderServices(userId, providerFilter);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
@@ -388,7 +357,9 @@ public final class CredentialManager {
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static boolean isServiceEnabled(Context context) {
|
||||
@TestApi
|
||||
public static boolean isServiceEnabled(@NonNull Context context) {
|
||||
requireNonNull(context, "context must not be null");
|
||||
if (context == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -578,33 +549,6 @@ public final class CredentialManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static class ListEnabledProvidersTransport extends IListEnabledProvidersCallback.Stub {
|
||||
// TODO: listen for cancellation to release callback.
|
||||
|
||||
private final Executor mExecutor;
|
||||
private final OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
|
||||
mCallback;
|
||||
|
||||
private ListEnabledProvidersTransport(
|
||||
Executor executor,
|
||||
OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException>
|
||||
callback) {
|
||||
mExecutor = executor;
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResponse(ListEnabledProvidersResponse response) {
|
||||
mExecutor.execute(() -> mCallback.onResult(response));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(String errorType, String message) {
|
||||
mExecutor.execute(
|
||||
() -> mCallback.onError(new ListEnabledProvidersException(errorType, message)));
|
||||
}
|
||||
}
|
||||
|
||||
private static class SetEnabledProvidersTransport extends ISetEnabledProvidersCallback.Stub {
|
||||
// TODO: listen for cancellation to release callback.
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
* Copyright 2023 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.
|
||||
@@ -16,14 +16,4 @@
|
||||
|
||||
package android.credentials;
|
||||
|
||||
import android.credentials.ListEnabledProvidersResponse;
|
||||
|
||||
/**
|
||||
* Listener for an listEnabledProviders request.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
interface IListEnabledProvidersCallback {
|
||||
oneway void onResponse(in ListEnabledProvidersResponse response);
|
||||
oneway void onError(String errorType, String message);
|
||||
}
|
||||
parcelable CredentialProviderInfo;
|
||||
215
core/java/android/credentials/CredentialProviderInfo.java
Normal file
215
core/java/android/credentials/CredentialProviderInfo.java
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TestApi;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* {@link ServiceInfo} and meta-data about a credential provider.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
public final class CredentialProviderInfo implements Parcelable {
|
||||
@NonNull private final ServiceInfo mServiceInfo;
|
||||
@NonNull private final List<String> mCapabilities = new ArrayList<>();
|
||||
@Nullable private final CharSequence mOverrideLabel;
|
||||
private final boolean mIsSystemProvider;
|
||||
private final boolean mIsEnabled;
|
||||
|
||||
/**
|
||||
* Constructs an information instance of the credential provider.
|
||||
*
|
||||
* @param builder the builder object.
|
||||
*/
|
||||
private CredentialProviderInfo(@NonNull Builder builder) {
|
||||
mServiceInfo = builder.mServiceInfo;
|
||||
mCapabilities.addAll(builder.mCapabilities);
|
||||
mIsSystemProvider = builder.mIsSystemProvider;
|
||||
mIsEnabled = builder.mIsEnabled;
|
||||
mOverrideLabel = builder.mOverrideLabel;
|
||||
}
|
||||
|
||||
/** Returns true if the service supports the given {@code credentialType}, false otherwise. */
|
||||
@NonNull
|
||||
public boolean hasCapability(@NonNull String credentialType) {
|
||||
return mCapabilities.contains(credentialType);
|
||||
}
|
||||
|
||||
/** Returns the service info. */
|
||||
@NonNull
|
||||
public ServiceInfo getServiceInfo() {
|
||||
return mServiceInfo;
|
||||
}
|
||||
|
||||
/** Returns whether it is a system provider. */
|
||||
public boolean isSystemProvider() {
|
||||
return mIsSystemProvider;
|
||||
}
|
||||
|
||||
/** Returns the service icon. */
|
||||
@Nullable
|
||||
public Drawable getServiceIcon(@NonNull Context context) {
|
||||
return mServiceInfo.loadIcon(context.getPackageManager());
|
||||
}
|
||||
|
||||
/** Returns the service label. */
|
||||
@Nullable
|
||||
public CharSequence getLabel(@NonNull Context context) {
|
||||
if (mOverrideLabel != null) {
|
||||
return mOverrideLabel;
|
||||
}
|
||||
return mServiceInfo.loadSafeLabel(context.getPackageManager());
|
||||
}
|
||||
|
||||
/** Returns a list of capabilities this provider service can support. */
|
||||
@NonNull
|
||||
public List<String> getCapabilities() {
|
||||
return Collections.unmodifiableList(mCapabilities);
|
||||
}
|
||||
|
||||
/** Returns whether the provider is enabled by the user. */
|
||||
public boolean isEnabled() {
|
||||
return mIsEnabled;
|
||||
}
|
||||
|
||||
/** Returns the component name for the service. */
|
||||
@NonNull
|
||||
public ComponentName getComponentName() {
|
||||
return mServiceInfo.getComponentName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeTypedObject(mServiceInfo, flags);
|
||||
dest.writeBoolean(mIsSystemProvider);
|
||||
dest.writeStringList(mCapabilities);
|
||||
dest.writeBoolean(mIsEnabled);
|
||||
TextUtils.writeToParcel(mOverrideLabel, dest, flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CredentialProviderInfo {"
|
||||
+ "serviceInfo="
|
||||
+ mServiceInfo
|
||||
+ ", "
|
||||
+ "isSystemProvider="
|
||||
+ mIsSystemProvider
|
||||
+ ", "
|
||||
+ "isEnabled="
|
||||
+ mIsEnabled
|
||||
+ ", "
|
||||
+ "overrideLabel="
|
||||
+ mOverrideLabel
|
||||
+ ", "
|
||||
+ "capabilities="
|
||||
+ String.join(",", mCapabilities)
|
||||
+ "}";
|
||||
}
|
||||
|
||||
private CredentialProviderInfo(@NonNull Parcel in) {
|
||||
mServiceInfo = in.readTypedObject(ServiceInfo.CREATOR);
|
||||
mIsSystemProvider = in.readBoolean();
|
||||
in.readStringList(mCapabilities);
|
||||
mIsEnabled = in.readBoolean();
|
||||
mOverrideLabel = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
|
||||
}
|
||||
|
||||
public static final @NonNull Parcelable.Creator<CredentialProviderInfo> CREATOR =
|
||||
new Parcelable.Creator<CredentialProviderInfo>() {
|
||||
@Override
|
||||
public CredentialProviderInfo[] newArray(int size) {
|
||||
return new CredentialProviderInfo[size];
|
||||
}
|
||||
|
||||
@Override
|
||||
public CredentialProviderInfo createFromParcel(@NonNull Parcel in) {
|
||||
return new CredentialProviderInfo(in);
|
||||
}
|
||||
};
|
||||
|
||||
/** A builder for {@link CredentialProviderInfo} objects. */
|
||||
public static final class Builder {
|
||||
|
||||
@NonNull private ServiceInfo mServiceInfo;
|
||||
@NonNull private List<String> mCapabilities = new ArrayList<>();
|
||||
private boolean mIsSystemProvider = false;
|
||||
private boolean mIsEnabled = false;
|
||||
@Nullable private CharSequence mOverrideLabel = null;
|
||||
|
||||
/**
|
||||
* Creates a new builder.
|
||||
*
|
||||
* @param serviceInfo the service info of the credential provider service.
|
||||
*/
|
||||
public Builder(@NonNull ServiceInfo serviceInfo) {
|
||||
mServiceInfo = serviceInfo;
|
||||
}
|
||||
|
||||
/** Sets whether it is a system provider. */
|
||||
public @NonNull Builder setSystemProvider(boolean isSystemProvider) {
|
||||
mIsSystemProvider = isSystemProvider;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the label to be used instead of getting from the system (for unit tests).
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public @NonNull Builder setOverrideLabel(@NonNull CharSequence overrideLabel) {
|
||||
mOverrideLabel = overrideLabel;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets a list of capabilities this provider service can support. */
|
||||
public @NonNull Builder addCapabilities(@NonNull List<String> capabilities) {
|
||||
mCapabilities.addAll(capabilities);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Sets whether it is enabled by the user. */
|
||||
public @NonNull Builder setEnabled(boolean isEnabled) {
|
||||
mIsEnabled = isEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Builds a new {@link CredentialProviderInfo} instance. */
|
||||
public @NonNull CredentialProviderInfo build() {
|
||||
return new CredentialProviderInfo(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ package android.credentials;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ClearCredentialStateRequest;
|
||||
import android.credentials.CreateCredentialRequest;
|
||||
import android.credentials.GetCredentialRequest;
|
||||
@@ -27,7 +27,6 @@ import android.credentials.UnregisterCredentialDescriptionRequest;
|
||||
import android.credentials.IClearCredentialStateCallback;
|
||||
import android.credentials.ICreateCredentialCallback;
|
||||
import android.credentials.IGetCredentialCallback;
|
||||
import android.credentials.IListEnabledProvidersCallback;
|
||||
import android.credentials.ISetEnabledProvidersCallback;
|
||||
import android.content.ComponentName;
|
||||
import android.os.ICancellationSignal;
|
||||
@@ -45,8 +44,6 @@ interface ICredentialManager {
|
||||
|
||||
@nullable ICancellationSignal clearCredentialState(in ClearCredentialStateRequest request, in IClearCredentialStateCallback callback, String callingPackage);
|
||||
|
||||
@nullable ICancellationSignal listEnabledProviders(in IListEnabledProvidersCallback callback);
|
||||
|
||||
void setEnabledProviders(in List<String> providers, in int userId, in ISetEnabledProvidersCallback callback);
|
||||
|
||||
void registerCredentialDescription(in RegisterCredentialDescriptionRequest request, String callingPackage);
|
||||
@@ -55,6 +52,8 @@ interface ICredentialManager {
|
||||
|
||||
boolean isEnabledCredentialProviderService(in ComponentName componentName, String callingPackage);
|
||||
|
||||
List<ServiceInfo> getCredentialProviderServices(in int userId, in boolean disableSystemAppVerificationForTests, in int providerFilter);
|
||||
List<CredentialProviderInfo> getCredentialProviderServices(in int userId, in int providerFilter);
|
||||
|
||||
List<CredentialProviderInfo> getCredentialProviderServicesForTesting(in int providerFilter);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,40 +34,27 @@ import android.content.pm.ResolveInfo;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.credentials.CredentialManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.RemoteException;
|
||||
import android.text.TextUtils;
|
||||
import android.os.UserHandle;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* {@link ServiceInfo} and meta-data about a credential provider.
|
||||
* {@link CredentialProviderInfo} generator.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public final class CredentialProviderInfo {
|
||||
private static final String TAG = "CredentialProviderInfo";
|
||||
|
||||
@NonNull
|
||||
private final ServiceInfo mServiceInfo;
|
||||
@NonNull
|
||||
private final List<String> mCapabilities;
|
||||
|
||||
@NonNull
|
||||
private final Context mContext;
|
||||
@Nullable
|
||||
private final Drawable mIcon;
|
||||
@Nullable
|
||||
private final CharSequence mLabel;
|
||||
private final boolean mIsSystemProvider;
|
||||
public final class CredentialProviderInfoFactory {
|
||||
private static final String TAG = "CredentialProviderInfoFactory";
|
||||
|
||||
/**
|
||||
* Constructs an information instance of the credential provider.
|
||||
@@ -79,14 +66,18 @@ public final class CredentialProviderInfo {
|
||||
* @throws PackageManager.NameNotFoundException If provider service is not found
|
||||
* @throws SecurityException If provider does not require the relevant permission
|
||||
*/
|
||||
public CredentialProviderInfo(@NonNull Context context,
|
||||
@NonNull ComponentName serviceComponent, int userId, boolean isSystemProvider)
|
||||
public static CredentialProviderInfo create(
|
||||
@NonNull Context context,
|
||||
@NonNull ComponentName serviceComponent,
|
||||
int userId,
|
||||
boolean isSystemProvider)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
this(
|
||||
return create(
|
||||
context,
|
||||
getServiceInfoOrThrow(serviceComponent, userId),
|
||||
isSystemProvider,
|
||||
/* disableSystemAppVerificationForTests= */ false);
|
||||
/* disableSystemAppVerificationForTests= */ false,
|
||||
/* isEnabled= */ false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,13 +89,16 @@ public final class CredentialProviderInfo {
|
||||
* @param isSystemProvider whether the provider app is a system provider
|
||||
* @param disableSystemAppVerificationForTests whether to disable system app permission
|
||||
* verification so that tests can install system providers
|
||||
* @param isEnabled whether the user enabled this provider
|
||||
* @throws SecurityException If provider does not require the relevant permission
|
||||
*/
|
||||
public CredentialProviderInfo(
|
||||
public static CredentialProviderInfo create(
|
||||
@NonNull Context context,
|
||||
@NonNull ServiceInfo serviceInfo,
|
||||
boolean isSystemProvider,
|
||||
boolean disableSystemAppVerificationForTests) {
|
||||
boolean disableSystemAppVerificationForTests,
|
||||
boolean isEnabled)
|
||||
throws SecurityException {
|
||||
verifyProviderPermission(serviceInfo);
|
||||
if (isSystemProvider) {
|
||||
if (!isValidSystemProvider(
|
||||
@@ -114,23 +108,11 @@ public final class CredentialProviderInfo {
|
||||
"Provider is not a valid system provider: " + serviceInfo);
|
||||
}
|
||||
}
|
||||
mIsSystemProvider = isSystemProvider;
|
||||
mContext = requireNonNull(context, "context must not be null");
|
||||
mServiceInfo = requireNonNull(serviceInfo, "serviceInfo must not be null");
|
||||
mCapabilities = new ArrayList<>();
|
||||
mIcon = mServiceInfo.loadIcon(mContext.getPackageManager());
|
||||
mLabel =
|
||||
mServiceInfo.loadSafeLabel(
|
||||
mContext.getPackageManager(),
|
||||
0 /* do not ellipsize */,
|
||||
TextUtils.SAFE_STRING_FLAG_FIRST_LINE | TextUtils.SAFE_STRING_FLAG_TRIM);
|
||||
Log.i(
|
||||
TAG,
|
||||
"mLabel is : "
|
||||
+ mLabel
|
||||
+ ", for: "
|
||||
+ mServiceInfo.getComponentName().flattenToString());
|
||||
populateProviderCapabilities(context, serviceInfo);
|
||||
|
||||
return populateMetadata(context, serviceInfo)
|
||||
.setSystemProvider(isSystemProvider)
|
||||
.setEnabled(isEnabled)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static void verifyProviderPermission(ServiceInfo serviceInfo) throws SecurityException {
|
||||
@@ -138,19 +120,14 @@ public final class CredentialProviderInfo {
|
||||
if (permission.equals(serviceInfo.permission)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Slog.e(
|
||||
TAG,
|
||||
"Credential Provider Service from : "
|
||||
+ serviceInfo.packageName
|
||||
+ "does not require permission"
|
||||
+ permission);
|
||||
throw new SecurityException(
|
||||
"Service does not require the expected permission : " + permission);
|
||||
}
|
||||
|
||||
private static boolean isSystemProviderWithValidPermission(
|
||||
ServiceInfo serviceInfo, Context context) {
|
||||
requireNonNull(context, "context must not be null");
|
||||
|
||||
final String permission = Manifest.permission.PROVIDE_DEFAULT_ENABLED_CREDENTIAL_SERVICE;
|
||||
try {
|
||||
ApplicationInfo appInfo =
|
||||
@@ -177,67 +154,88 @@ public final class CredentialProviderInfo {
|
||||
Context context,
|
||||
ServiceInfo serviceInfo,
|
||||
boolean disableSystemAppVerificationForTests) {
|
||||
boolean isValidSystemTestProvider =
|
||||
isTestSystemProvider(serviceInfo, disableSystemAppVerificationForTests);
|
||||
if (isValidSystemTestProvider) {
|
||||
return true;
|
||||
requireNonNull(context, "context must not be null");
|
||||
|
||||
if (disableSystemAppVerificationForTests) {
|
||||
Bundle metadata = serviceInfo.metaData;
|
||||
if (metadata == null) {
|
||||
Slog.e(TAG, "isValidSystemProvider - metadata is null: " + serviceInfo);
|
||||
return false;
|
||||
}
|
||||
return metadata.getBoolean(
|
||||
CredentialProviderService.TEST_SYSTEM_PROVIDER_META_DATA_KEY);
|
||||
}
|
||||
|
||||
return isSystemProviderWithValidPermission(serviceInfo, context);
|
||||
}
|
||||
|
||||
private static boolean isTestSystemProvider(
|
||||
ServiceInfo serviceInfo, boolean disableSystemAppVerificationForTests) {
|
||||
if (!disableSystemAppVerificationForTests) {
|
||||
return false;
|
||||
}
|
||||
private static CredentialProviderInfo.Builder populateMetadata(
|
||||
@NonNull Context context, ServiceInfo serviceInfo) {
|
||||
requireNonNull(context, "context must not be null");
|
||||
|
||||
Bundle metadata = serviceInfo.metaData;
|
||||
if (metadata == null) {
|
||||
Slog.e(TAG, "metadata is null: " + serviceInfo);
|
||||
return false;
|
||||
}
|
||||
return metadata.getBoolean(CredentialProviderService.TEST_SYSTEM_PROVIDER_META_DATA_KEY);
|
||||
}
|
||||
|
||||
private void populateProviderCapabilities(@NonNull Context context, ServiceInfo serviceInfo) {
|
||||
final CredentialProviderInfo.Builder builder =
|
||||
new CredentialProviderInfo.Builder(serviceInfo);
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
|
||||
// 1. Get the metadata for the service.
|
||||
final Bundle metadata = serviceInfo.metaData;
|
||||
if (metadata == null) {
|
||||
Log.i(TAG, "populateMetadata - metadata is null");
|
||||
return builder;
|
||||
}
|
||||
|
||||
// 2. Extract the capabilities from the bundle.
|
||||
try {
|
||||
Bundle metadata = serviceInfo.metaData;
|
||||
Resources resources = pm.getResourcesForApplication(serviceInfo.applicationInfo);
|
||||
if (metadata == null || resources == null) {
|
||||
Log.i(TAG, "populateProviderCapabilities - metadata or resources is null");
|
||||
return;
|
||||
Log.i(TAG, "populateMetadata - resources is null");
|
||||
return builder;
|
||||
}
|
||||
|
||||
String[] capabilities = resources.getStringArray(metadata.getInt(
|
||||
CredentialProviderService.CAPABILITY_META_DATA_KEY));
|
||||
if (capabilities == null || capabilities.length == 0) {
|
||||
Slog.i(TAG, "No capabilities found for provider:" + serviceInfo.packageName);
|
||||
return;
|
||||
}
|
||||
|
||||
for (String capability : capabilities) {
|
||||
if (capability.isEmpty()) {
|
||||
Slog.i(TAG, "Skipping empty capability");
|
||||
continue;
|
||||
}
|
||||
Slog.i(TAG, "Capabilities found for provider: " + capability);
|
||||
mCapabilities.add(capability);
|
||||
}
|
||||
builder.addCapabilities(populateProviderCapabilities(resources, metadata, serviceInfo));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Slog.e(TAG, e.getMessage());
|
||||
} catch (Resources.NotFoundException e) {
|
||||
Slog.e(TAG, e.getMessage());
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
private static ServiceInfo getServiceInfoOrThrow(@NonNull ComponentName serviceComponent,
|
||||
int userId) throws PackageManager.NameNotFoundException {
|
||||
private static List<String> populateProviderCapabilities(
|
||||
Resources resources, Bundle metadata, ServiceInfo serviceInfo) {
|
||||
List<String> output = new ArrayList<>();
|
||||
String[] capabilities = new String[0];
|
||||
|
||||
try {
|
||||
ServiceInfo si = AppGlobals.getPackageManager().getServiceInfo(
|
||||
serviceComponent,
|
||||
PackageManager.GET_META_DATA,
|
||||
userId);
|
||||
capabilities =
|
||||
resources.getStringArray(
|
||||
metadata.getInt(CredentialProviderService.CAPABILITY_META_DATA_KEY));
|
||||
} catch (Resources.NotFoundException e) {
|
||||
Slog.e(TAG, "Failed to get capabilities: " + e.getMessage());
|
||||
}
|
||||
|
||||
if (capabilities == null || capabilities.length == 0) {
|
||||
Slog.e(TAG, "No capabilities found for provider:" + serviceInfo.packageName);
|
||||
return output;
|
||||
}
|
||||
|
||||
for (String capability : capabilities) {
|
||||
if (capability.isEmpty()) {
|
||||
Slog.e(TAG, "Skipping empty capability");
|
||||
continue;
|
||||
}
|
||||
Slog.e(TAG, "Capabilities found for provider: " + capability);
|
||||
output.add(capability);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
private static ServiceInfo getServiceInfoOrThrow(
|
||||
@NonNull ComponentName serviceComponent, int userId)
|
||||
throws PackageManager.NameNotFoundException {
|
||||
try {
|
||||
ServiceInfo si =
|
||||
AppGlobals.getPackageManager()
|
||||
.getServiceInfo(serviceComponent, PackageManager.GET_META_DATA, userId);
|
||||
if (si != null) {
|
||||
return si;
|
||||
}
|
||||
@@ -256,6 +254,8 @@ public final class CredentialProviderInfo {
|
||||
@NonNull Context context,
|
||||
@UserIdInt int userId,
|
||||
boolean disableSystemAppVerificationForTests) {
|
||||
requireNonNull(context, "context must not be null");
|
||||
|
||||
final List<ServiceInfo> services = new ArrayList<>();
|
||||
final List<ResolveInfo> resolveInfos = new ArrayList<>();
|
||||
|
||||
@@ -268,15 +268,20 @@ public final class CredentialProviderInfo {
|
||||
|
||||
for (ResolveInfo resolveInfo : resolveInfos) {
|
||||
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
|
||||
if (disableSystemAppVerificationForTests) {
|
||||
if (serviceInfo != null) {
|
||||
services.add(serviceInfo);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
PackageManager.ApplicationInfoFlags appInfoFlags =
|
||||
disableSystemAppVerificationForTests
|
||||
? PackageManager.ApplicationInfoFlags.of(0)
|
||||
: PackageManager.ApplicationInfoFlags.of(
|
||||
PackageManager.MATCH_SYSTEM_ONLY);
|
||||
ApplicationInfo appInfo =
|
||||
context.getPackageManager()
|
||||
.getApplicationInfo(serviceInfo.packageName, appInfoFlags);
|
||||
.getApplicationInfo(
|
||||
serviceInfo.packageName,
|
||||
PackageManager.ApplicationInfoFlags.of(
|
||||
PackageManager.MATCH_SYSTEM_ONLY));
|
||||
|
||||
if (appInfo == null || serviceInfo == null) {
|
||||
continue;
|
||||
@@ -300,19 +305,22 @@ public final class CredentialProviderInfo {
|
||||
public static List<CredentialProviderInfo> getAvailableSystemServices(
|
||||
@NonNull Context context,
|
||||
@UserIdInt int userId,
|
||||
boolean disableSystemAppVerificationForTests) {
|
||||
boolean disableSystemAppVerificationForTests,
|
||||
Set<ServiceInfo> enabledServices) {
|
||||
requireNonNull(context, "context must not be null");
|
||||
|
||||
final List<CredentialProviderInfo> providerInfos = new ArrayList<>();
|
||||
for (ServiceInfo si :
|
||||
getAvailableSystemServiceInfos(
|
||||
context, userId, disableSystemAppVerificationForTests)) {
|
||||
try {
|
||||
CredentialProviderInfo cpi =
|
||||
new CredentialProviderInfo(
|
||||
CredentialProviderInfoFactory.create(
|
||||
context,
|
||||
si,
|
||||
/* isSystemProvider= */ true,
|
||||
disableSystemAppVerificationForTests);
|
||||
disableSystemAppVerificationForTests,
|
||||
enabledServices.contains(si));
|
||||
if (cpi.isSystemProvider()) {
|
||||
providerInfos.add(cpi);
|
||||
} else {
|
||||
@@ -325,45 +333,12 @@ public final class CredentialProviderInfo {
|
||||
return providerInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the service supports the given {@code credentialType}, false otherwise.
|
||||
*/
|
||||
@NonNull
|
||||
public boolean hasCapability(@NonNull String credentialType) {
|
||||
return mCapabilities.contains(credentialType);
|
||||
}
|
||||
private static @Nullable PackagePolicy getDeviceManagerPolicy(
|
||||
@NonNull Context context, int userId) {
|
||||
Context newContext = context.createContextAsUser(UserHandle.of(userId), 0);
|
||||
|
||||
/** Returns the service info. */
|
||||
@NonNull
|
||||
public ServiceInfo getServiceInfo() {
|
||||
return mServiceInfo;
|
||||
}
|
||||
|
||||
public boolean isSystemProvider() {
|
||||
return mIsSystemProvider;
|
||||
}
|
||||
|
||||
/** Returns the service icon. */
|
||||
@Nullable
|
||||
public Drawable getServiceIcon() {
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
/** Returns the service label. */
|
||||
@Nullable
|
||||
public CharSequence getServiceLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
/** Returns an immutable list of capabilities this provider service can support. */
|
||||
@NonNull
|
||||
public List<String> getCapabilities() {
|
||||
return Collections.unmodifiableList(mCapabilities);
|
||||
}
|
||||
|
||||
private static @Nullable PackagePolicy getDeviceManagerPolicy(@NonNull Context context) {
|
||||
try {
|
||||
DevicePolicyManager dpm = context.getSystemService(DevicePolicyManager.class);
|
||||
DevicePolicyManager dpm = newContext.getSystemService(DevicePolicyManager.class);
|
||||
return dpm.getCredentialManagerPolicy();
|
||||
} catch (SecurityException e) {
|
||||
// If the current user is not enrolled in DPM then this can throw a security error.
|
||||
@@ -381,21 +356,53 @@ public final class CredentialProviderInfo {
|
||||
public static List<CredentialProviderInfo> getCredentialProviderServices(
|
||||
@NonNull Context context,
|
||||
int userId,
|
||||
boolean disableSystemAppVerificationForTests,
|
||||
int providerFilter) {
|
||||
int providerFilter,
|
||||
Set<ServiceInfo> enabledServices) {
|
||||
requireNonNull(context, "context must not be null");
|
||||
|
||||
// Get the device policy.
|
||||
PackagePolicy pp = getDeviceManagerPolicy(context);
|
||||
PackagePolicy pp = getDeviceManagerPolicy(context, userId);
|
||||
|
||||
// Generate the provider list.
|
||||
final boolean disableSystemAppVerificationForTests = false;
|
||||
ProviderGenerator generator =
|
||||
new ProviderGenerator(
|
||||
context, pp, disableSystemAppVerificationForTests, providerFilter);
|
||||
generator.addUserProviders(
|
||||
getUserProviders(context, userId, disableSystemAppVerificationForTests));
|
||||
getUserProviders(
|
||||
context, userId, disableSystemAppVerificationForTests, enabledServices));
|
||||
generator.addSystemProviders(
|
||||
getAvailableSystemServices(context, userId, disableSystemAppVerificationForTests));
|
||||
getAvailableSystemServices(
|
||||
context, userId, disableSystemAppVerificationForTests, enabledServices));
|
||||
return generator.getProviders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the valid credential provider services available for the user with the given {@code
|
||||
* userId}. Includes test providers.
|
||||
*/
|
||||
@NonNull
|
||||
public static List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
|
||||
@NonNull Context context,
|
||||
int userId,
|
||||
int providerFilter,
|
||||
Set<ServiceInfo> enabledServices) {
|
||||
requireNonNull(context, "context must not be null");
|
||||
|
||||
// Get the device policy.
|
||||
PackagePolicy pp = getDeviceManagerPolicy(context, userId);
|
||||
|
||||
// Generate the provider list.
|
||||
final boolean disableSystemAppVerificationForTests = true;
|
||||
ProviderGenerator generator =
|
||||
new ProviderGenerator(
|
||||
context, pp, disableSystemAppVerificationForTests, providerFilter);
|
||||
generator.addUserProviders(
|
||||
getUserProviders(
|
||||
context, userId, disableSystemAppVerificationForTests, enabledServices));
|
||||
generator.addSystemProviders(
|
||||
getAvailableSystemServices(
|
||||
context, userId, disableSystemAppVerificationForTests, enabledServices));
|
||||
return generator.getProviders();
|
||||
}
|
||||
|
||||
@@ -484,7 +491,8 @@ public final class CredentialProviderInfo {
|
||||
private static List<CredentialProviderInfo> getUserProviders(
|
||||
@NonNull Context context,
|
||||
@UserIdInt int userId,
|
||||
boolean disableSystemAppVerificationForTests) {
|
||||
boolean disableSystemAppVerificationForTests,
|
||||
Set<ServiceInfo> enabledServices) {
|
||||
final List<CredentialProviderInfo> services = new ArrayList<>();
|
||||
final List<ResolveInfo> resolveInfos =
|
||||
context.getPackageManager()
|
||||
@@ -496,11 +504,12 @@ public final class CredentialProviderInfo {
|
||||
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
|
||||
try {
|
||||
CredentialProviderInfo cpi =
|
||||
new CredentialProviderInfo(
|
||||
CredentialProviderInfoFactory.create(
|
||||
context,
|
||||
serviceInfo,
|
||||
/* isSystemProvider= */ false,
|
||||
disableSystemAppVerificationForTests);
|
||||
disableSystemAppVerificationForTests,
|
||||
enabledServices.contains(serviceInfo));
|
||||
if (!cpi.isSystemProvider()) {
|
||||
services.add(cpi);
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import static org.mockito.Mockito.when;
|
||||
import android.app.Activity;
|
||||
import android.app.slice.Slice;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
@@ -47,6 +48,7 @@ import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
@@ -59,6 +61,17 @@ public class CredentialManagerTest {
|
||||
@Mock
|
||||
private Activity mMockActivity;
|
||||
|
||||
private static final int TEST_USER_ID = 1;
|
||||
private static final CredentialProviderInfo TEST_CREDENTIAL_PROVIDER_INFO =
|
||||
new CredentialProviderInfo.Builder(new ServiceInfo())
|
||||
.setSystemProvider(true)
|
||||
.setOverrideLabel("test")
|
||||
.addCapabilities(Arrays.asList("passkey"))
|
||||
.setEnabled(true)
|
||||
.build();
|
||||
private static final List<CredentialProviderInfo> TEST_CREDENTIAL_PROVIDER_INFO_LIST =
|
||||
Arrays.asList(TEST_CREDENTIAL_PROVIDER_INFO);
|
||||
|
||||
private GetCredentialRequest mGetRequest;
|
||||
private CreateCredentialRequest mCreateRequest;
|
||||
|
||||
@@ -438,95 +451,53 @@ public class CredentialManagerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListEnabledProviders_nullExecutor() {
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> mCredentialManager.listEnabledProviders(null, null, result -> {
|
||||
}));
|
||||
|
||||
public void testGetCredentialProviderServices_allProviders() throws RemoteException {
|
||||
verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListEnabledProviders_nullCallback() {
|
||||
assertThrows(NullPointerException.class,
|
||||
() -> mCredentialManager.listEnabledProviders(null, mExecutor, null));
|
||||
|
||||
public void testGetCredentialProviderServices_userProviders() throws RemoteException {
|
||||
verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListEnabledProviders_alreadyCancelled() throws RemoteException {
|
||||
final CancellationSignal cancellation = new CancellationSignal();
|
||||
cancellation.cancel();
|
||||
|
||||
mCredentialManager.listEnabledProviders(cancellation, mExecutor, result -> {
|
||||
});
|
||||
|
||||
verify(mMockCredentialManagerService, never()).listEnabledProviders(any());
|
||||
public void testGetCredentialProviderServices_systemProviders() throws RemoteException {
|
||||
verifyGetCredentialProviderServices(CredentialManager.PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListEnabledProviders_cancel() throws RemoteException {
|
||||
final ICancellationSignal serviceSignal = mock(ICancellationSignal.class);
|
||||
final CancellationSignal cancellation = new CancellationSignal();
|
||||
|
||||
OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
|
||||
mock(OutcomeReceiver.class);
|
||||
|
||||
when(mMockCredentialManagerService.listEnabledProviders(any())).thenReturn(serviceSignal);
|
||||
|
||||
mCredentialManager.listEnabledProviders(cancellation, mExecutor, callback);
|
||||
|
||||
verify(mMockCredentialManagerService).listEnabledProviders(any());
|
||||
|
||||
cancellation.cancel();
|
||||
verify(serviceSignal).cancel();
|
||||
public void testGetCredentialProviderServicesForTesting_allProviders() throws RemoteException {
|
||||
verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListEnabledProviders_failed() throws RemoteException {
|
||||
ArgumentCaptor<IListEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
|
||||
IListEnabledProvidersCallback.class);
|
||||
ArgumentCaptor<ListEnabledProvidersException> errorCaptor = ArgumentCaptor.forClass(
|
||||
ListEnabledProvidersException.class);
|
||||
|
||||
OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
|
||||
mock(OutcomeReceiver.class);
|
||||
|
||||
when(mMockCredentialManagerService.listEnabledProviders(
|
||||
callbackCaptor.capture())).thenReturn(mock(ICancellationSignal.class));
|
||||
mCredentialManager.listEnabledProviders(null, mExecutor, callback);
|
||||
verify(mMockCredentialManagerService).listEnabledProviders(any());
|
||||
|
||||
final String errorType = "type";
|
||||
callbackCaptor.getValue().onError("type", "unknown error");
|
||||
verify(callback).onError(errorCaptor.capture());
|
||||
|
||||
assertThat(errorCaptor.getValue().getType()).isEqualTo(errorType);
|
||||
public void testGetCredentialProviderServicesForTesting_userProviders() throws RemoteException {
|
||||
verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListEnabledProviders_success() throws RemoteException {
|
||||
ListEnabledProvidersResponse response = ListEnabledProvidersResponse.create(
|
||||
List.of("foo", "bar", "baz"));
|
||||
public void testGetCredentialProviderServicesForTesting_systemProviders() throws RemoteException {
|
||||
verifyGetCredentialProviderServicesForTesting(CredentialManager.PROVIDER_FILTER_SYSTEM_PROVIDERS_ONLY);
|
||||
}
|
||||
|
||||
OutcomeReceiver<ListEnabledProvidersResponse, ListEnabledProvidersException> callback =
|
||||
mock(OutcomeReceiver.class);
|
||||
private void verifyGetCredentialProviderServices(int testFilter) throws RemoteException {
|
||||
when(mMockCredentialManagerService.getCredentialProviderServices(
|
||||
TEST_USER_ID, testFilter)).thenReturn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
|
||||
|
||||
ArgumentCaptor<IListEnabledProvidersCallback> callbackCaptor = ArgumentCaptor.forClass(
|
||||
IListEnabledProvidersCallback.class);
|
||||
ArgumentCaptor<ListEnabledProvidersResponse> responseCaptor = ArgumentCaptor.forClass(
|
||||
ListEnabledProvidersResponse.class);
|
||||
List<CredentialProviderInfo> output =
|
||||
mCredentialManager.getCredentialProviderServices(TEST_USER_ID, testFilter);
|
||||
|
||||
when(mMockCredentialManagerService.listEnabledProviders(
|
||||
callbackCaptor.capture())).thenReturn(mock(ICancellationSignal.class));
|
||||
mCredentialManager.listEnabledProviders(null, mExecutor, callback);
|
||||
assertThat(output).containsExactlyElementsIn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
|
||||
}
|
||||
|
||||
verify(mMockCredentialManagerService).listEnabledProviders(any());
|
||||
private void verifyGetCredentialProviderServicesForTesting(int testFilter) throws RemoteException {
|
||||
when(mMockCredentialManagerService.getCredentialProviderServicesForTesting(
|
||||
testFilter)).thenReturn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
|
||||
|
||||
callbackCaptor.getValue().onResponse(response);
|
||||
List<CredentialProviderInfo> output =
|
||||
mCredentialManager.getCredentialProviderServicesForTesting(testFilter);
|
||||
|
||||
verify(callback).onResult(responseCaptor.capture());
|
||||
assertThat(responseCaptor.getValue().getProviderComponentNames()).containsExactlyElementsIn(
|
||||
response.getProviderComponentNames());
|
||||
assertThat(output).containsExactlyElementsIn(TEST_CREDENTIAL_PROVIDER_INFO_LIST);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -20,13 +20,13 @@ import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.credentials.ClearCredentialStateRequest;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.IClearCredentialStateCallback;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.RequestInfo;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.server.credentials.metrics.ApiName;
|
||||
|
||||
@@ -27,13 +27,13 @@ import android.credentials.CreateCredentialException;
|
||||
import android.credentials.CreateCredentialRequest;
|
||||
import android.credentials.CreateCredentialResponse;
|
||||
import android.credentials.CredentialManager;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ICreateCredentialCallback;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.RequestInfo;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.server.credentials.metrics.ApiName;
|
||||
|
||||
@@ -36,15 +36,14 @@ import android.credentials.CreateCredentialRequest;
|
||||
import android.credentials.CredentialDescription;
|
||||
import android.credentials.CredentialManager;
|
||||
import android.credentials.CredentialOption;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.GetCredentialException;
|
||||
import android.credentials.GetCredentialRequest;
|
||||
import android.credentials.IClearCredentialStateCallback;
|
||||
import android.credentials.ICreateCredentialCallback;
|
||||
import android.credentials.ICredentialManager;
|
||||
import android.credentials.IGetCredentialCallback;
|
||||
import android.credentials.IListEnabledProvidersCallback;
|
||||
import android.credentials.ISetEnabledProvidersCallback;
|
||||
import android.credentials.ListEnabledProvidersResponse;
|
||||
import android.credentials.RegisterCredentialDescriptionRequest;
|
||||
import android.credentials.UnregisterCredentialDescriptionRequest;
|
||||
import android.credentials.ui.IntentFactory;
|
||||
@@ -56,7 +55,7 @@ import android.os.UserHandle;
|
||||
import android.provider.DeviceConfig;
|
||||
import android.provider.Settings;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.service.credentials.CredentialProviderInfoFactory;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
@@ -118,10 +117,11 @@ public final class CredentialManagerService
|
||||
int resolvedUserId) {
|
||||
List<CredentialManagerServiceImpl> services = new ArrayList<>();
|
||||
List<CredentialProviderInfo> serviceInfos =
|
||||
CredentialProviderInfo.getAvailableSystemServices(
|
||||
CredentialProviderInfoFactory.getAvailableSystemServices(
|
||||
mContext,
|
||||
resolvedUserId,
|
||||
/* disableSystemAppVerificationForTests= */ false);
|
||||
/* disableSystemAppVerificationForTests= */ false,
|
||||
new HashSet<>());
|
||||
serviceInfos.forEach(
|
||||
info -> {
|
||||
services.add(
|
||||
@@ -222,10 +222,16 @@ public final class CredentialManagerService
|
||||
return hasPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS);
|
||||
}
|
||||
|
||||
private void verifyPermission(String permission) throws SecurityException {
|
||||
if (!hasPermission(permission)) {
|
||||
throw new SecurityException("Caller is missing permission: " + permission);
|
||||
private void verifyGetProvidersPermission() throws SecurityException {
|
||||
if (hasPermission(android.Manifest.permission.QUERY_ALL_PACKAGES)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hasPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new SecurityException("Caller is missing permission: QUERY_ALL_PACKAGES or LIST_ENABLED_CREDENTIAL_PROVIDERS");
|
||||
}
|
||||
|
||||
private boolean hasPermission(String permission) {
|
||||
@@ -550,40 +556,6 @@ public final class CredentialManagerService
|
||||
providerSessions.forEach(ProviderSession::invokeSession);
|
||||
}
|
||||
|
||||
@SuppressWarnings("GuardedBy") // ErrorProne requires listEnabledProviders
|
||||
// to be guarded by 'service.mLock', which is the same as mLock.
|
||||
@Override
|
||||
public ICancellationSignal listEnabledProviders(IListEnabledProvidersCallback callback) {
|
||||
Log.i(TAG, "listEnabledProviders");
|
||||
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
|
||||
|
||||
if (!hasWriteSecureSettingsPermission()) {
|
||||
try {
|
||||
callback.onError(
|
||||
PERMISSION_DENIED_ERROR, PERMISSION_DENIED_WRITE_SECURE_SETTINGS_ERROR);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Issue with invoking response: " + e.getMessage());
|
||||
}
|
||||
return cancelTransport;
|
||||
}
|
||||
|
||||
List<String> enabledProviders = new ArrayList<>();
|
||||
runForUser(
|
||||
(service) -> {
|
||||
enabledProviders.add(service.getComponentName().flattenToString());
|
||||
});
|
||||
|
||||
// Call the callback.
|
||||
try {
|
||||
callback.onResponse(ListEnabledProvidersResponse.create(enabledProviders));
|
||||
} catch (RemoteException e) {
|
||||
Log.i(TAG, "Issue with invoking response: " + e.getMessage());
|
||||
// TODO: Propagate failure
|
||||
}
|
||||
|
||||
return cancelTransport;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setEnabledProviders(
|
||||
List<String> providers, int userId, ISetEnabledProvidersCallback callback) {
|
||||
@@ -677,20 +649,35 @@ public final class CredentialManagerService
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ServiceInfo> getCredentialProviderServices(
|
||||
int userId, boolean disableSystemAppVerificationForTests, int providerFilter) {
|
||||
public List<CredentialProviderInfo> getCredentialProviderServices(
|
||||
int userId, int providerFilter) {
|
||||
Log.i(TAG, "getCredentialProviderServices");
|
||||
verifyPermission(android.Manifest.permission.LIST_ENABLED_CREDENTIAL_PROVIDERS);
|
||||
verifyGetProvidersPermission();
|
||||
|
||||
List<ServiceInfo> services = new ArrayList<>();
|
||||
List<CredentialProviderInfo> providers =
|
||||
CredentialProviderInfo.getCredentialProviderServices(
|
||||
mContext, userId, disableSystemAppVerificationForTests, providerFilter);
|
||||
for (CredentialProviderInfo p : providers) {
|
||||
services.add(p.getServiceInfo());
|
||||
return CredentialProviderInfoFactory.getCredentialProviderServices(
|
||||
mContext, userId, providerFilter, getEnabledProviders());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CredentialProviderInfo> getCredentialProviderServicesForTesting(
|
||||
int providerFilter) {
|
||||
Log.i(TAG, "getCredentialProviderServicesForTesting");
|
||||
verifyGetProvidersPermission();
|
||||
|
||||
final int userId = UserHandle.getCallingUserId();
|
||||
return CredentialProviderInfoFactory.getCredentialProviderServicesForTesting(
|
||||
mContext, userId, providerFilter, getEnabledProviders());
|
||||
}
|
||||
|
||||
private Set<ServiceInfo> getEnabledProviders() {
|
||||
Set<ServiceInfo> enabledProviders = new HashSet<>();
|
||||
synchronized (mLock) {
|
||||
runForUser(
|
||||
(service) -> {
|
||||
enabledProviders.add(service.getCredentialProviderInfo().getServiceInfo());
|
||||
});
|
||||
}
|
||||
|
||||
return services;
|
||||
return enabledProviders;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -828,11 +815,11 @@ public final class CredentialManagerService
|
||||
}
|
||||
|
||||
private List<CredentialProviderInfo> getServicesForCredentialDescription(int userId) {
|
||||
return CredentialProviderInfo.getCredentialProviderServices(
|
||||
return CredentialProviderInfoFactory.getCredentialProviderServices(
|
||||
mContext,
|
||||
userId,
|
||||
/* disableSystemAppVerificationForTests= */ false,
|
||||
CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS);
|
||||
CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS,
|
||||
new HashSet<>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@ import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.service.credentials.CredentialProviderInfoFactory;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
@@ -82,7 +83,7 @@ public final class CredentialManagerServiceImpl extends
|
||||
Log.i(TAG, "newServiceInfoLocked with null mInfo , "
|
||||
+ serviceComponent.getPackageName());
|
||||
}
|
||||
mInfo = new CredentialProviderInfo(
|
||||
mInfo = CredentialProviderInfoFactory.create(
|
||||
getContext(), serviceComponent,
|
||||
mUserId, /*isSystemProvider=*/false);
|
||||
return mInfo.getServiceInfo();
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.ServiceInfo;
|
||||
import android.credentials.CredentialManager;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ui.DisabledProviderData;
|
||||
import android.credentials.ui.IntentFactory;
|
||||
import android.credentials.ui.ProviderData;
|
||||
@@ -31,11 +32,12 @@ import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.ResultReceiver;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.service.credentials.CredentialProviderInfoFactory;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -118,11 +120,11 @@ public class CredentialManagerUi {
|
||||
.map(ProviderData::getProviderFlattenedComponentName)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
Set<String> allProviders =
|
||||
CredentialProviderInfo.getCredentialProviderServices(
|
||||
CredentialProviderInfoFactory.getCredentialProviderServices(
|
||||
mContext,
|
||||
mUserId,
|
||||
/* disableSystemAppVerificationForTests= */ false,
|
||||
CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY)
|
||||
CredentialManager.PROVIDER_FILTER_USER_PROVIDERS_ONLY,
|
||||
new HashSet<>())
|
||||
.stream()
|
||||
.map(CredentialProviderInfo::getServiceInfo)
|
||||
.map(ServiceInfo::getComponentName)
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.android.server.credentials.MetricUtilities.METRICS_PROVIDER_ST
|
||||
import android.annotation.Nullable;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.GetCredentialException;
|
||||
import android.credentials.GetCredentialRequest;
|
||||
import android.credentials.GetCredentialResponse;
|
||||
@@ -31,7 +32,6 @@ import android.credentials.ui.RequestInfo;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.server.credentials.metrics.ApiName;
|
||||
|
||||
@@ -20,11 +20,11 @@ import android.annotation.Nullable;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.Context;
|
||||
import android.credentials.ClearCredentialStateException;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.ClearCredentialStateRequest;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.credentials.CreateCredentialException;
|
||||
import android.credentials.CreateCredentialResponse;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ui.CreateCredentialProviderData;
|
||||
import android.credentials.ui.Entry;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
@@ -33,7 +34,6 @@ import android.service.credentials.BeginCreateCredentialResponse;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CreateCredentialRequest;
|
||||
import android.service.credentials.CreateEntry;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.service.credentials.CredentialProviderService;
|
||||
import android.service.credentials.RemoteEntry;
|
||||
import android.util.Log;
|
||||
|
||||
@@ -23,6 +23,7 @@ import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.credentials.CredentialOption;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.GetCredentialException;
|
||||
import android.credentials.GetCredentialResponse;
|
||||
import android.credentials.ui.AuthenticationEntry;
|
||||
@@ -35,7 +36,6 @@ import android.service.credentials.BeginGetCredentialRequest;
|
||||
import android.service.credentials.BeginGetCredentialResponse;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CredentialEntry;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.service.credentials.CredentialProviderService;
|
||||
import android.service.credentials.GetCredentialRequest;
|
||||
import android.service.credentials.RemoteEntry;
|
||||
|
||||
@@ -27,11 +27,11 @@ import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.credentials.Credential;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.server.credentials.metrics.CandidateProviderMetric;
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.UserSelectionDialogResult;
|
||||
import android.os.Binder;
|
||||
@@ -30,7 +31,6 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.service.credentials.CredentialProviderInfo;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.R;
|
||||
|
||||
Reference in New Issue
Block a user