1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.credentials; 18 19 import android.annotation.Nullable; 20 import android.annotation.UserIdInt; 21 import android.content.Context; 22 import android.credentials.ClearCredentialStateException; 23 import android.credentials.CredentialProviderInfo; 24 import android.credentials.ui.ProviderData; 25 import android.credentials.ui.ProviderPendingIntentResponse; 26 import android.os.ICancellationSignal; 27 import android.service.credentials.CallingAppInfo; 28 import android.service.credentials.ClearCredentialStateRequest; 29 import android.util.Slog; 30 31 /** 32 * Central provider session that listens for provider callbacks, and maintains provider state. 33 * 34 * @hide 35 */ 36 public final class ProviderClearSession extends ProviderSession<ClearCredentialStateRequest, 37 Void> 38 implements 39 RemoteCredentialService.ProviderCallbacks<Void> { 40 private static final String TAG = "ProviderClearSession"; 41 42 private ClearCredentialStateException mProviderException; 43 44 /** Creates a new provider session to be used by the request session. */ 45 @Nullable createNewSession( Context context, @UserIdInt int userId, CredentialProviderInfo providerInfo, ClearRequestSession clearRequestSession, RemoteCredentialService remoteCredentialService)46 public static ProviderClearSession createNewSession( 47 Context context, 48 @UserIdInt int userId, 49 CredentialProviderInfo providerInfo, 50 ClearRequestSession clearRequestSession, 51 RemoteCredentialService remoteCredentialService) { 52 ClearCredentialStateRequest providerRequest = 53 createProviderRequest( 54 clearRequestSession.mClientRequest, 55 clearRequestSession.mClientAppInfo); 56 return new ProviderClearSession(context, providerInfo, clearRequestSession, userId, 57 remoteCredentialService, providerRequest); 58 } 59 60 @Nullable createProviderRequest( android.credentials.ClearCredentialStateRequest clientRequest, CallingAppInfo callingAppInfo )61 private static ClearCredentialStateRequest createProviderRequest( 62 android.credentials.ClearCredentialStateRequest clientRequest, 63 CallingAppInfo callingAppInfo 64 ) { 65 return new ClearCredentialStateRequest( 66 callingAppInfo, 67 clientRequest.getData()); 68 } 69 ProviderClearSession(Context context, CredentialProviderInfo info, ProviderInternalCallback callbacks, int userId, RemoteCredentialService remoteCredentialService, ClearCredentialStateRequest providerRequest)70 public ProviderClearSession(Context context, 71 CredentialProviderInfo info, 72 ProviderInternalCallback callbacks, 73 int userId, RemoteCredentialService remoteCredentialService, 74 ClearCredentialStateRequest providerRequest) { 75 super(context, providerRequest, callbacks, info.getComponentName(), 76 userId, remoteCredentialService); 77 setStatus(Status.PENDING); 78 } 79 80 @Override onProviderResponseSuccess(@ullable Void response)81 public void onProviderResponseSuccess(@Nullable Void response) { 82 Slog.i(TAG, "Remote provider responded with a valid response: " + mComponentName); 83 mProviderResponseSet = true; 84 updateStatusAndInvokeCallback(Status.COMPLETE, 85 /*source=*/ CredentialsSource.REMOTE_PROVIDER); 86 } 87 88 /** Called when the provider response resulted in a failure. */ 89 @Override // Callback from the remote provider onProviderResponseFailure(int errorCode, Exception exception)90 public void onProviderResponseFailure(int errorCode, Exception exception) { 91 if (exception instanceof ClearCredentialStateException) { 92 mProviderException = (ClearCredentialStateException) exception; 93 // TODO(b/271135048) : Decide on exception type length 94 mProviderSessionMetric.collectCandidateFrameworkException(mProviderException.getType()); 95 } 96 mProviderSessionMetric.collectCandidateExceptionStatus(/*hasException=*/true); 97 updateStatusAndInvokeCallback(Status.CANCELED, 98 /*source=*/ CredentialsSource.REMOTE_PROVIDER); 99 } 100 101 /** Called when provider service dies. */ 102 @Override // Callback from the remote provider onProviderServiceDied(RemoteCredentialService service)103 public void onProviderServiceDied(RemoteCredentialService service) { 104 if (service.getComponentName().equals(mComponentName)) { 105 updateStatusAndInvokeCallback(Status.SERVICE_DEAD, 106 /*source=*/ CredentialsSource.REMOTE_PROVIDER); 107 } else { 108 Slog.w(TAG, "Component names different in onProviderServiceDied - " 109 + "this should not happen"); 110 } 111 } 112 113 @Override onProviderCancellable(ICancellationSignal cancellation)114 public void onProviderCancellable(ICancellationSignal cancellation) { 115 mProviderCancellationSignal = cancellation; 116 } 117 118 @Nullable 119 @Override prepareUiData()120 protected ProviderData prepareUiData() { 121 //Not applicable for clearCredential as response is not picked by the user 122 return null; 123 } 124 125 @Override onUiEntrySelected(String entryType, String entryId, ProviderPendingIntentResponse providerPendingIntentResponse)126 protected void onUiEntrySelected(String entryType, String entryId, 127 ProviderPendingIntentResponse providerPendingIntentResponse) { 128 //Not applicable for clearCredential as response is not picked by the user 129 } 130 131 @Override invokeSession()132 protected void invokeSession() { 133 if (mRemoteCredentialService != null) { 134 startCandidateMetrics(); 135 mRemoteCredentialService.setCallback(this); 136 mRemoteCredentialService.onClearCredentialState(mProviderRequest); 137 } 138 } 139 } 140