Add API to check if credman is enabled
Adds an API that can be called by provider apps to see if they are enabled. Test: Make Bug: 253157366 API-Coverage-Bug: 247549381 Change-Id: I61e64b21437165303ca16656b86c8814b27e26b7
This commit is contained in:
@@ -13507,6 +13507,7 @@ package android.credentials {
|
||||
method public void clearCredentialState(@NonNull android.credentials.ClearCredentialStateRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.credentials.ClearCredentialStateException>);
|
||||
method public void createCredential(@NonNull android.credentials.CreateCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.CreateCredentialResponse,android.credentials.CreateCredentialException>);
|
||||
method public void getCredential(@NonNull android.credentials.GetCredentialRequest, @NonNull android.app.Activity, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<android.credentials.GetCredentialResponse,android.credentials.GetCredentialException>);
|
||||
method public boolean isEnabledCredentialProviderService(@NonNull android.content.ComponentName);
|
||||
method public void registerCredentialDescription(@NonNull android.credentials.RegisterCredentialDescriptionRequest);
|
||||
method public void unregisterCredentialDescription(@NonNull android.credentials.UnregisterCredentialDescriptionRequest);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemService;
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.IntentSender;
|
||||
import android.os.CancellationSignal;
|
||||
@@ -279,6 +280,25 @@ public final class CredentialManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the calling application provides a CredentialProviderService that is
|
||||
* enabled for the current user, or {@code false} otherwise. CredentialProviderServices are
|
||||
* enabled on a per-service basis so the individual component name of the service should be
|
||||
* passed in here.
|
||||
*
|
||||
* @param componentName the component name to check is enabled
|
||||
*/
|
||||
public boolean isEnabledCredentialProviderService(@NonNull ComponentName componentName) {
|
||||
requireNonNull(componentName, "componentName must not be null");
|
||||
|
||||
try {
|
||||
return mService.isEnabledCredentialProviderService(
|
||||
componentName, mContext.getOpPackageName());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the service is enabled.
|
||||
*
|
||||
@@ -286,7 +306,7 @@ public final class CredentialManager {
|
||||
*/
|
||||
public static boolean isServiceEnabled(Context context) {
|
||||
if (context == null) {
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
CredentialManager credentialManager =
|
||||
(CredentialManager) context.getSystemService(Context.CREDENTIAL_SERVICE);
|
||||
@@ -298,8 +318,7 @@ public final class CredentialManager {
|
||||
|
||||
private boolean isServiceEnabled() {
|
||||
return DeviceConfig.getBoolean(
|
||||
DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_MANAGER,
|
||||
true);
|
||||
DeviceConfig.NAMESPACE_CREDENTIAL, DEVICE_CONFIG_ENABLE_CREDENTIAL_MANAGER, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -313,22 +332,19 @@ public final class CredentialManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a {@link CredentialDescription} for an actively provisioned {@link Credential}
|
||||
* a CredentialProvider has. This registry will then be used to determine where to
|
||||
* fetch the requested {@link Credential} from. Not all credential types will be supported.
|
||||
* The distinction will be made by the JetPack layer. For the types that are supported,
|
||||
* JetPack will add a new key-value pair into {@link GetCredentialRequest}. These will not
|
||||
* be persistent on the device. The Credential Providers will need to call this API again
|
||||
* upon device reboot.
|
||||
* Registers a {@link CredentialDescription} for an actively provisioned {@link Credential} a
|
||||
* CredentialProvider has. This registry will then be used to determine where to fetch the
|
||||
* requested {@link Credential} from. Not all credential types will be supported. The
|
||||
* distinction will be made by the JetPack layer. For the types that are supported, JetPack will
|
||||
* add a new key-value pair into {@link GetCredentialRequest}. These will not be persistent on
|
||||
* the device. The Credential Providers will need to call this API again upon device reboot.
|
||||
*
|
||||
* @param request the request data
|
||||
*
|
||||
* @throws {@link UnsupportedOperationException} if the feature has not been enabled.
|
||||
* @throws {@link com.android.server.credentials.NonCredentialProviderCallerException}
|
||||
* if the calling package name is not also listed as a Credential Provider.
|
||||
* @throws {@link IllegalArgumentException} if the calling Credential Provider can not handle
|
||||
* one or more of the Credential Types that are sent for registration.
|
||||
*
|
||||
* @throws {@link UnsupportedOperationException} if the feature has not been enabled.
|
||||
* @throws {@link com.android.server.credentials.NonCredentialProviderCallerException} if the
|
||||
* calling package name is not also listed as a Credential Provider.
|
||||
* @throws {@link IllegalArgumentException} if the calling Credential Provider can not handle
|
||||
* one or more of the Credential Types that are sent for registration.
|
||||
*/
|
||||
public void registerCredentialDescription(
|
||||
@NonNull RegisterCredentialDescriptionRequest request) {
|
||||
@@ -346,16 +362,12 @@ public final class CredentialManager {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unregisters a {@link CredentialDescription} for an actively provisioned {@link Credential}
|
||||
* Unregisters a {@link CredentialDescription} for an actively provisioned {@link Credential}
|
||||
* that has been registered previously.
|
||||
*
|
||||
*
|
||||
* @param request the request data
|
||||
*
|
||||
* @throws {@link UnsupportedOperationException} if the feature has not been enabled.
|
||||
*
|
||||
* @throws {@link UnsupportedOperationException} if the feature has not been enabled.
|
||||
*/
|
||||
public void unregisterCredentialDescription(
|
||||
@NonNull UnregisterCredentialDescriptionRequest request) {
|
||||
@@ -371,7 +383,6 @@ public final class CredentialManager {
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class GetCredentialTransport extends IGetCredentialCallback.Stub {
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.credentials.ICreateCredentialCallback;
|
||||
import android.credentials.IGetCredentialCallback;
|
||||
import android.credentials.IListEnabledProvidersCallback;
|
||||
import android.credentials.ISetEnabledProvidersCallback;
|
||||
import android.content.ComponentName;
|
||||
import android.os.ICancellationSignal;
|
||||
|
||||
/**
|
||||
@@ -50,5 +51,7 @@ interface ICredentialManager {
|
||||
void registerCredentialDescription(in RegisterCredentialDescriptionRequest request, String callingPackage);
|
||||
|
||||
void unregisterCredentialDescription(in UnregisterCredentialDescriptionRequest request, String callingPackage);
|
||||
|
||||
boolean isEnabledCredentialProviderService(in ComponentName componentName, String callingPackage);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,14 +84,11 @@ public final class CredentialManagerService
|
||||
|
||||
private final Context mContext;
|
||||
|
||||
/**
|
||||
* Cache of system service list per user id.
|
||||
*/
|
||||
/** Cache of system service list per user id. */
|
||||
@GuardedBy("mLock")
|
||||
private final SparseArray<List<CredentialManagerServiceImpl>> mSystemServicesCacheList =
|
||||
new SparseArray<>();
|
||||
|
||||
|
||||
public CredentialManagerService(@NonNull Context context) {
|
||||
super(
|
||||
context,
|
||||
@@ -109,9 +106,11 @@ public final class CredentialManagerService
|
||||
List<CredentialManagerServiceImpl> services = new ArrayList<>();
|
||||
List<CredentialProviderInfo> credentialProviderInfos =
|
||||
CredentialProviderInfo.getAvailableSystemServices(mContext, resolvedUserId);
|
||||
credentialProviderInfos.forEach(info -> {
|
||||
services.add(new CredentialManagerServiceImpl(this, mLock, resolvedUserId, info));
|
||||
});
|
||||
credentialProviderInfos.forEach(
|
||||
info -> {
|
||||
services.add(
|
||||
new CredentialManagerServiceImpl(this, mLock, resolvedUserId, info));
|
||||
});
|
||||
return services;
|
||||
}
|
||||
|
||||
@@ -174,10 +173,9 @@ public final class CredentialManagerService
|
||||
CredentialManagerServiceImpl serviceToBeRemoved = null;
|
||||
for (CredentialManagerServiceImpl service : services) {
|
||||
if (service != null) {
|
||||
CredentialProviderInfo credentialProviderInfo =
|
||||
service.getCredentialProviderInfo();
|
||||
ComponentName componentName = credentialProviderInfo.getServiceInfo()
|
||||
.getComponentName();
|
||||
CredentialProviderInfo credentialProviderInfo = service.getCredentialProviderInfo();
|
||||
ComponentName componentName =
|
||||
credentialProviderInfo.getServiceInfo().getComponentName();
|
||||
if (packageName.equals(componentName.getPackageName())) {
|
||||
serviceToBeRemoved = service;
|
||||
removeServiceFromMultiModeSettings(componentName.flattenToString(), userId);
|
||||
@@ -193,7 +191,6 @@ public final class CredentialManagerService
|
||||
// TODO("Iterate over system services and remove if needed")
|
||||
}
|
||||
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private List<CredentialManagerServiceImpl> getOrConstructSystemServiceListLock(
|
||||
int resolvedUserId) {
|
||||
@@ -222,8 +219,7 @@ public final class CredentialManagerService
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
private List<CredentialManagerServiceImpl> getAllCredentialProviderServicesLocked(
|
||||
int userId) {
|
||||
private List<CredentialManagerServiceImpl> getAllCredentialProviderServicesLocked(int userId) {
|
||||
List<CredentialManagerServiceImpl> concatenatedServices = new ArrayList<>();
|
||||
List<CredentialManagerServiceImpl> userConfigurableServices =
|
||||
getServiceListForUserLocked(userId);
|
||||
@@ -243,16 +239,18 @@ public final class CredentialManagerService
|
||||
// to be guarded by 'service.mLock', which is the same as mLock.
|
||||
private List<ProviderSession> initiateProviderSessionsWithActiveContainers(
|
||||
GetRequestSession session,
|
||||
List<String> requestOptions, Set<String> activeCredentialContainers) {
|
||||
List<String> requestOptions,
|
||||
Set<String> activeCredentialContainers) {
|
||||
List<ProviderSession> providerSessions = new ArrayList<>();
|
||||
// Invoke all services of a user to initiate a provider session
|
||||
for (String packageName: activeCredentialContainers) {
|
||||
providerSessions.add(ProviderRegistryGetSession.createNewSession(
|
||||
mContext,
|
||||
UserHandle.getCallingUserId(),
|
||||
session,
|
||||
packageName,
|
||||
requestOptions));
|
||||
for (String packageName : activeCredentialContainers) {
|
||||
providerSessions.add(
|
||||
ProviderRegistryGetSession.createNewSession(
|
||||
mContext,
|
||||
UserHandle.getCallingUserId(),
|
||||
session,
|
||||
packageName,
|
||||
requestOptions));
|
||||
}
|
||||
return providerSessions;
|
||||
}
|
||||
@@ -260,16 +258,17 @@ public final class CredentialManagerService
|
||||
@NonNull
|
||||
private Set<String> getFilteredResultFromRegistry(List<CredentialOption> options) {
|
||||
// Session for active/provisioned credential descriptions;
|
||||
CredentialDescriptionRegistry registry = CredentialDescriptionRegistry
|
||||
.forUser(UserHandle.getCallingUserId());
|
||||
CredentialDescriptionRegistry registry =
|
||||
CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
|
||||
|
||||
// All requested credential descriptions based on the given request.
|
||||
Set<String> requestedCredentialDescriptions =
|
||||
options.stream().map(
|
||||
getCredentialOption -> getCredentialOption
|
||||
.getCredentialRetrievalData()
|
||||
.getString(CredentialOption
|
||||
.FLATTENED_REQUEST))
|
||||
options.stream()
|
||||
.map(
|
||||
getCredentialOption ->
|
||||
getCredentialOption
|
||||
.getCredentialRetrievalData()
|
||||
.getString(CredentialOption.FLATTENED_REQUEST))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
// All requested credential descriptions based on the given request.
|
||||
@@ -306,10 +305,14 @@ public final class CredentialManagerService
|
||||
private CallingAppInfo constructCallingAppInfo(String packageName, int userId) {
|
||||
final PackageInfo packageInfo;
|
||||
try {
|
||||
packageInfo = getContext().getPackageManager().getPackageInfoAsUser(
|
||||
packageName,
|
||||
PackageManager.PackageInfoFlags.of(PackageManager.GET_SIGNING_CERTIFICATES),
|
||||
userId);
|
||||
packageInfo =
|
||||
getContext()
|
||||
.getPackageManager()
|
||||
.getPackageInfoAsUser(
|
||||
packageName,
|
||||
PackageManager.PackageInfoFlags.of(
|
||||
PackageManager.GET_SIGNING_CERTIFICATES),
|
||||
userId);
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.i(TAG, "Issue while retrieving signatureInfo : " + e.getMessage());
|
||||
return new CallingAppInfo(packageName, null);
|
||||
@@ -345,37 +348,50 @@ public final class CredentialManagerService
|
||||
if (isCredentialDescriptionApiEnabled()) {
|
||||
List<CredentialOption> optionsThatRequireActiveCredentials =
|
||||
request.getCredentialOptions().stream()
|
||||
.filter(getCredentialOption ->
|
||||
!TextUtils.isEmpty(getCredentialOption
|
||||
.getCredentialRetrievalData().getString(
|
||||
CredentialOption
|
||||
.FLATTENED_REQUEST, null)))
|
||||
.filter(
|
||||
getCredentialOption ->
|
||||
!TextUtils.isEmpty(
|
||||
getCredentialOption
|
||||
.getCredentialRetrievalData()
|
||||
.getString(
|
||||
CredentialOption
|
||||
.FLATTENED_REQUEST,
|
||||
null)))
|
||||
.toList();
|
||||
|
||||
List<CredentialOption> optionsThatDoNotRequireActiveCredentials =
|
||||
request.getCredentialOptions().stream()
|
||||
.filter(getCredentialOption ->
|
||||
TextUtils.isEmpty(getCredentialOption
|
||||
.getCredentialRetrievalData().getString(
|
||||
CredentialOption
|
||||
.FLATTENED_REQUEST, null)))
|
||||
.filter(
|
||||
getCredentialOption ->
|
||||
TextUtils.isEmpty(
|
||||
getCredentialOption
|
||||
.getCredentialRetrievalData()
|
||||
.getString(
|
||||
CredentialOption
|
||||
.FLATTENED_REQUEST,
|
||||
null)))
|
||||
.toList();
|
||||
|
||||
List<ProviderSession> sessionsWithoutRemoteService =
|
||||
initiateProviderSessionsWithActiveContainers(session,
|
||||
optionsThatRequireActiveCredentials
|
||||
.stream().map(getCredentialOption ->
|
||||
getCredentialOption.getCredentialRetrievalData()
|
||||
.getString(CredentialOption
|
||||
.FLATTENED_REQUEST))
|
||||
initiateProviderSessionsWithActiveContainers(
|
||||
session,
|
||||
optionsThatRequireActiveCredentials.stream()
|
||||
.map(
|
||||
getCredentialOption ->
|
||||
getCredentialOption
|
||||
.getCredentialRetrievalData()
|
||||
.getString(
|
||||
CredentialOption
|
||||
.FLATTENED_REQUEST))
|
||||
.collect(Collectors.toList()),
|
||||
getFilteredResultFromRegistry(optionsThatRequireActiveCredentials));
|
||||
|
||||
List<ProviderSession> sessionsWithRemoteService = initiateProviderSessions(
|
||||
session,
|
||||
optionsThatDoNotRequireActiveCredentials.stream()
|
||||
.map(CredentialOption::getType)
|
||||
.collect(Collectors.toList()));
|
||||
List<ProviderSession> sessionsWithRemoteService =
|
||||
initiateProviderSessions(
|
||||
session,
|
||||
optionsThatDoNotRequireActiveCredentials.stream()
|
||||
.map(CredentialOption::getType)
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
Set<ProviderSession> all = new LinkedHashSet<>();
|
||||
all.addAll(sessionsWithRemoteService);
|
||||
@@ -394,7 +410,8 @@ public final class CredentialManagerService
|
||||
|
||||
if (providerSessions.isEmpty()) {
|
||||
try {
|
||||
callback.onError(GetCredentialException.TYPE_NO_CREDENTIAL,
|
||||
callback.onError(
|
||||
GetCredentialException.TYPE_NO_CREDENTIAL,
|
||||
"No credentials available on this device.");
|
||||
} catch (RemoteException e) {
|
||||
Log.i(
|
||||
@@ -437,7 +454,8 @@ public final class CredentialManagerService
|
||||
|
||||
if (providerSessions.isEmpty()) {
|
||||
try {
|
||||
callback.onError(CreateCredentialException.TYPE_NO_CREDENTIAL,
|
||||
callback.onError(
|
||||
CreateCredentialException.TYPE_NO_CREDENTIAL,
|
||||
"No credentials available on this device.");
|
||||
} catch (RemoteException e) {
|
||||
Log.i(
|
||||
@@ -521,6 +539,37 @@ public final class CredentialManagerService
|
||||
getContext().sendBroadcast(IntentFactory.createProviderUpdateIntent());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledCredentialProviderService(
|
||||
ComponentName componentName, String callingPackage) {
|
||||
Log.i(TAG, "isEnabledCredentialProviderService");
|
||||
|
||||
// TODO(253157366): Check additional set of services.
|
||||
final int userId = UserHandle.getCallingUserId();
|
||||
synchronized (mLock) {
|
||||
final List<CredentialManagerServiceImpl> services =
|
||||
getServiceListForUserLocked(userId);
|
||||
for (CredentialManagerServiceImpl s : services) {
|
||||
final ComponentName serviceComponentName = s.getServiceComponentName();
|
||||
|
||||
if (serviceComponentName.equals(componentName)) {
|
||||
if (!s.getServicePackageName().equals(callingPackage)) {
|
||||
// The component name and the package name do not match.
|
||||
Log.w(
|
||||
TAG,
|
||||
"isEnabledCredentialProviderService: Component name does not"
|
||||
+ " match package name.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICancellationSignal clearCredentialState(
|
||||
ClearCredentialStateRequest request,
|
||||
@@ -550,8 +599,7 @@ public final class CredentialManagerService
|
||||
if (providerSessions.isEmpty()) {
|
||||
try {
|
||||
// TODO("Replace with properly defined error type")
|
||||
callback.onError("UNKNOWN", "No crdentials available on this "
|
||||
+ "device");
|
||||
callback.onError("UNKNOWN", "No crdentials available on this " + "device");
|
||||
} catch (RemoteException e) {
|
||||
Log.i(
|
||||
TAG,
|
||||
@@ -569,39 +617,50 @@ public final class CredentialManagerService
|
||||
@Override
|
||||
public void registerCredentialDescription(
|
||||
RegisterCredentialDescriptionRequest request, String callingPackage)
|
||||
throws IllegalArgumentException , NonCredentialProviderCallerException {
|
||||
throws IllegalArgumentException, NonCredentialProviderCallerException {
|
||||
Log.i(TAG, "registerCredentialDescription");
|
||||
|
||||
List<CredentialProviderInfo> services =
|
||||
CredentialProviderInfo.getAvailableServices(mContext,
|
||||
UserHandle.getCallingUserId());
|
||||
CredentialProviderInfo.getAvailableServices(
|
||||
mContext, UserHandle.getCallingUserId());
|
||||
|
||||
List<String> providers = services.stream()
|
||||
.map(credentialProviderInfo
|
||||
-> credentialProviderInfo.getServiceInfo().packageName).toList();
|
||||
List<String> providers =
|
||||
services.stream()
|
||||
.map(
|
||||
credentialProviderInfo ->
|
||||
credentialProviderInfo.getServiceInfo().packageName)
|
||||
.toList();
|
||||
|
||||
if (!providers.contains(callingPackage)) {
|
||||
throw new NonCredentialProviderCallerException(callingPackage);
|
||||
}
|
||||
|
||||
List<CredentialProviderInfo> matchingService = services.stream().filter(
|
||||
credentialProviderInfo ->
|
||||
credentialProviderInfo.getServiceInfo()
|
||||
.packageName.equals(callingPackage)).toList();
|
||||
List<CredentialProviderInfo> matchingService =
|
||||
services.stream()
|
||||
.filter(
|
||||
credentialProviderInfo ->
|
||||
credentialProviderInfo
|
||||
.getServiceInfo()
|
||||
.packageName
|
||||
.equals(callingPackage))
|
||||
.toList();
|
||||
|
||||
CredentialProviderInfo credentialProviderInfo = matchingService.get(0);
|
||||
|
||||
Set<String> supportedTypes = request.getCredentialDescriptions()
|
||||
.stream().map(CredentialDescription::getType).filter(
|
||||
credentialProviderInfo::hasCapability).collect(Collectors.toSet());
|
||||
Set<String> supportedTypes =
|
||||
request.getCredentialDescriptions().stream()
|
||||
.map(CredentialDescription::getType)
|
||||
.filter(credentialProviderInfo::hasCapability)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (supportedTypes.size() != request.getCredentialDescriptions().size()) {
|
||||
throw new IllegalArgumentException("CredentialProvider does not support one or more"
|
||||
+ "of the registered types. Check your XML entry.");
|
||||
throw new IllegalArgumentException(
|
||||
"CredentialProvider does not support one or more"
|
||||
+ "of the registered types. Check your XML entry.");
|
||||
}
|
||||
|
||||
CredentialDescriptionRegistry session = CredentialDescriptionRegistry
|
||||
.forUser(UserHandle.getCallingUserId());
|
||||
CredentialDescriptionRegistry session =
|
||||
CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
|
||||
|
||||
session.executeRegisterRequest(request, callingPackage);
|
||||
}
|
||||
@@ -614,19 +673,22 @@ public final class CredentialManagerService
|
||||
ICancellationSignal cancelTransport = CancellationSignal.createTransport();
|
||||
|
||||
List<CredentialProviderInfo> services =
|
||||
CredentialProviderInfo.getAvailableServices(mContext,
|
||||
UserHandle.getCallingUserId());
|
||||
CredentialProviderInfo.getAvailableServices(
|
||||
mContext, UserHandle.getCallingUserId());
|
||||
|
||||
List<String> providers = services.stream()
|
||||
.map(credentialProviderInfo
|
||||
-> credentialProviderInfo.getServiceInfo().packageName).toList();
|
||||
List<String> providers =
|
||||
services.stream()
|
||||
.map(
|
||||
credentialProviderInfo ->
|
||||
credentialProviderInfo.getServiceInfo().packageName)
|
||||
.toList();
|
||||
|
||||
if (!providers.contains(callingPackage)) {
|
||||
throw new NonCredentialProviderCallerException(callingPackage);
|
||||
}
|
||||
|
||||
CredentialDescriptionRegistry session = CredentialDescriptionRegistry
|
||||
.forUser(UserHandle.getCallingUserId());
|
||||
CredentialDescriptionRegistry session =
|
||||
CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
|
||||
|
||||
session.executeUnregisterRequest(request, callingPackage);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user