Merge "Listen to live cancellation signal" into udc-dev
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* 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
|
||||
* http://www.apache.org/licenses/LICENSE-2.0N
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -74,7 +74,6 @@ class CredentialSelectorActivity : ComponentActivity() {
|
||||
override fun onNewIntent(intent: Intent) {
|
||||
super.onNewIntent(intent)
|
||||
setIntent(intent)
|
||||
Log.d(Constants.LOG_TAG, "Existing activity received new intent")
|
||||
try {
|
||||
val viewModel: CredentialSelectorViewModel by viewModels()
|
||||
val (isCancellationRequest, shouldShowCancellationUi, appDisplayName) =
|
||||
|
||||
@@ -40,11 +40,13 @@ public final class ClearRequestSession extends RequestSession<ClearCredentialSta
|
||||
implements ProviderSession.ProviderInternalCallback<Void> {
|
||||
private static final String TAG = "GetRequestSession";
|
||||
|
||||
public ClearRequestSession(Context context, int userId, int callingUid,
|
||||
public ClearRequestSession(Context context, RequestSession.SessionLifetime sessionCallback,
|
||||
Object lock, int userId, int callingUid,
|
||||
IClearCredentialStateCallback callback, ClearCredentialStateRequest request,
|
||||
CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal,
|
||||
long startedTimestamp) {
|
||||
super(context, userId, callingUid, request, callback, RequestInfo.TYPE_UNDEFINED,
|
||||
super(context, sessionCallback, lock, userId, callingUid, request, callback,
|
||||
RequestInfo.TYPE_UNDEFINED,
|
||||
callingAppInfo, cancellationSignal, startedTimestamp);
|
||||
}
|
||||
|
||||
|
||||
@@ -49,13 +49,15 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
|
||||
implements ProviderSession.ProviderInternalCallback<CreateCredentialResponse> {
|
||||
private static final String TAG = "CreateRequestSession";
|
||||
|
||||
CreateRequestSession(@NonNull Context context, int userId, int callingUid,
|
||||
CreateRequestSession(@NonNull Context context, RequestSession.SessionLifetime sessionCallback,
|
||||
Object lock, int userId, int callingUid,
|
||||
CreateCredentialRequest request,
|
||||
ICreateCredentialCallback callback,
|
||||
CallingAppInfo callingAppInfo,
|
||||
CancellationSignal cancellationSignal,
|
||||
long startedTimestamp) {
|
||||
super(context, userId, callingUid, request, callback, RequestInfo.TYPE_CREATE,
|
||||
super(context, sessionCallback, lock, userId, callingUid, request, callback,
|
||||
RequestInfo.TYPE_CREATE,
|
||||
callingAppInfo, cancellationSignal, startedTimestamp);
|
||||
}
|
||||
|
||||
@@ -83,6 +85,7 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
|
||||
@Override
|
||||
protected void launchUiWithProviderData(ArrayList<ProviderData> providerDataList) {
|
||||
mRequestSessionMetric.collectUiCallStartTime(System.nanoTime());
|
||||
mCredentialManagerUi.setStatus(CredentialManagerUi.UiStatus.USER_INTERACTION);
|
||||
try {
|
||||
mClientCallback.onPendingIntent(mCredentialManagerUi.createPendingIntent(
|
||||
RequestInfo.newCreateRequestInfo(
|
||||
@@ -93,6 +96,7 @@ public final class CreateRequestSession extends RequestSession<CreateCredentialR
|
||||
providerDataList));
|
||||
} catch (RemoteException e) {
|
||||
mRequestSessionMetric.collectUiReturnedFinalPhase(/*uiReturned=*/ false);
|
||||
mCredentialManagerUi.setStatus(CredentialManagerUi.UiStatus.TERMINATED);
|
||||
respondToClientWithErrorAndFinish(
|
||||
CreateCredentialException.TYPE_UNKNOWN,
|
||||
"Unable to invoke selector");
|
||||
|
||||
@@ -33,7 +33,6 @@ import android.content.pm.PackageManager;
|
||||
import android.credentials.ClearCredentialStateRequest;
|
||||
import android.credentials.CreateCredentialException;
|
||||
import android.credentials.CreateCredentialRequest;
|
||||
import android.credentials.CredentialManager;
|
||||
import android.credentials.CredentialOption;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.GetCredentialException;
|
||||
@@ -50,6 +49,7 @@ import android.credentials.UnregisterCredentialDescriptionRequest;
|
||||
import android.credentials.ui.IntentFactory;
|
||||
import android.os.Binder;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.IBinder;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
@@ -70,9 +70,11 @@ import com.android.server.infra.AbstractMasterSystemService;
|
||||
import com.android.server.infra.SecureSettingsServiceNameResolver;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -102,6 +104,13 @@ public final class CredentialManagerService
|
||||
private final SparseArray<List<CredentialManagerServiceImpl>> mSystemServicesCacheList =
|
||||
new SparseArray<>();
|
||||
|
||||
/** Cache of all ongoing request sessions per user id. */
|
||||
@GuardedBy("mLock")
|
||||
private final SparseArray<Map<IBinder, RequestSession>> mRequestSessions =
|
||||
new SparseArray<>();
|
||||
|
||||
private final SessionManager mSessionManager = new SessionManager();
|
||||
|
||||
public CredentialManagerService(@NonNull Context context) {
|
||||
super(
|
||||
context,
|
||||
@@ -331,7 +340,7 @@ public final class CredentialManagerService
|
||||
|
||||
@NonNull
|
||||
private Set<Pair<CredentialOption, CredentialDescriptionRegistry.FilterResult>>
|
||||
getFilteredResultFromRegistry(List<CredentialOption> options) {
|
||||
getFilteredResultFromRegistry(List<CredentialOption> options) {
|
||||
// Session for active/provisioned credential descriptions;
|
||||
CredentialDescriptionRegistry registry =
|
||||
CredentialDescriptionRegistry.forUser(UserHandle.getCallingUserId());
|
||||
@@ -389,14 +398,6 @@ public final class CredentialManagerService
|
||||
return providerSessions;
|
||||
}
|
||||
|
||||
private List<CredentialProviderInfo> getServicesForCredentialDescription(int userId) {
|
||||
return CredentialProviderInfoFactory.getCredentialProviderServices(
|
||||
mContext,
|
||||
userId,
|
||||
CredentialManager.PROVIDER_FILTER_ALL_PROVIDERS,
|
||||
new HashSet<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
@GuardedBy("CredentialDescriptionRegistry.sLock")
|
||||
public void onUserStopped(@NonNull TargetUser user) {
|
||||
@@ -448,6 +449,8 @@ public final class CredentialManagerService
|
||||
final GetRequestSession session =
|
||||
new GetRequestSession(
|
||||
getContext(),
|
||||
mSessionManager,
|
||||
mLock,
|
||||
userId,
|
||||
callingUid,
|
||||
callback,
|
||||
@@ -455,6 +458,7 @@ public final class CredentialManagerService
|
||||
constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
|
||||
CancellationSignal.fromTransport(cancelTransport),
|
||||
timestampBegan);
|
||||
addSessionLocked(userId, session);
|
||||
|
||||
List<ProviderSession> providerSessions =
|
||||
prepareProviderSessions(request, session);
|
||||
@@ -499,6 +503,8 @@ public final class CredentialManagerService
|
||||
final PrepareGetRequestSession session =
|
||||
new PrepareGetRequestSession(
|
||||
getContext(),
|
||||
mSessionManager,
|
||||
mLock,
|
||||
userId,
|
||||
callingUid,
|
||||
getCredentialCallback,
|
||||
@@ -515,8 +521,8 @@ public final class CredentialManagerService
|
||||
// TODO: fix
|
||||
prepareGetCredentialCallback.onResponse(
|
||||
new PrepareGetCredentialResponseInternal(
|
||||
false, null,
|
||||
false, false, null));
|
||||
false, null,
|
||||
false, false, null));
|
||||
} catch (RemoteException e) {
|
||||
Log.i(
|
||||
TAG,
|
||||
@@ -540,10 +546,10 @@ public final class CredentialManagerService
|
||||
List<CredentialOption> optionsThatRequireActiveCredentials =
|
||||
request.getCredentialOptions().stream()
|
||||
.filter(credentialOption -> credentialOption
|
||||
.getCredentialRetrievalData()
|
||||
.getStringArrayList(
|
||||
CredentialOption
|
||||
.SUPPORTED_ELEMENT_KEYS) != null)
|
||||
.getCredentialRetrievalData()
|
||||
.getStringArrayList(
|
||||
CredentialOption
|
||||
.SUPPORTED_ELEMENT_KEYS) != null)
|
||||
.toList();
|
||||
|
||||
List<CredentialOption> optionsThatDoNotRequireActiveCredentials =
|
||||
@@ -614,6 +620,8 @@ public final class CredentialManagerService
|
||||
final CreateRequestSession session =
|
||||
new CreateRequestSession(
|
||||
getContext(),
|
||||
mSessionManager,
|
||||
mLock,
|
||||
userId,
|
||||
callingUid,
|
||||
request,
|
||||
@@ -621,6 +629,7 @@ public final class CredentialManagerService
|
||||
constructCallingAppInfo(callingPackage, userId, request.getOrigin()),
|
||||
CancellationSignal.fromTransport(cancelTransport),
|
||||
timestampBegan);
|
||||
addSessionLocked(userId, session);
|
||||
|
||||
processCreateCredential(request, callback, session);
|
||||
return cancelTransport;
|
||||
@@ -815,6 +824,8 @@ public final class CredentialManagerService
|
||||
final ClearRequestSession session =
|
||||
new ClearRequestSession(
|
||||
getContext(),
|
||||
mSessionManager,
|
||||
mLock,
|
||||
userId,
|
||||
callingUid,
|
||||
callback,
|
||||
@@ -822,6 +833,7 @@ public final class CredentialManagerService
|
||||
constructCallingAppInfo(callingPackage, userId, null),
|
||||
CancellationSignal.fromTransport(cancelTransport),
|
||||
timestampBegan);
|
||||
addSessionLocked(userId, session);
|
||||
|
||||
// Initiate all provider sessions
|
||||
// TODO: Determine if provider needs to have clear capability in their manifest
|
||||
@@ -905,6 +917,13 @@ public final class CredentialManagerService
|
||||
}
|
||||
}
|
||||
|
||||
private void addSessionLocked(@UserIdInt int userId,
|
||||
RequestSession requestSession) {
|
||||
synchronized (mLock) {
|
||||
mSessionManager.addSession(userId, requestSession.mRequestId, requestSession);
|
||||
}
|
||||
}
|
||||
|
||||
private void enforceCallingPackage(String callingPackage, int callingUid) {
|
||||
int packageUid;
|
||||
PackageManager pm = mContext.createContextAsUser(
|
||||
@@ -919,4 +938,23 @@ public final class CredentialManagerService
|
||||
throw new SecurityException(callingPackage + " does not belong to uid " + callingUid);
|
||||
}
|
||||
}
|
||||
|
||||
private class SessionManager implements RequestSession.SessionLifetime {
|
||||
@Override
|
||||
@GuardedBy("mLock")
|
||||
public void onFinishRequestSession(@UserIdInt int userId, IBinder token) {
|
||||
Log.i(TAG, "In onFinishRequestSession");
|
||||
if (mRequestSessions.get(userId) != null) {
|
||||
mRequestSessions.get(userId).remove(token);
|
||||
}
|
||||
}
|
||||
|
||||
@GuardedBy("mLock")
|
||||
public void addSession(int userId, IBinder token, RequestSession requestSession) {
|
||||
if (mRequestSessions.get(userId) == null) {
|
||||
mRequestSessions.put(userId, new HashMap<>());
|
||||
}
|
||||
mRequestSessions.get(userId).put(token, requestSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.credentials.ui.RequestInfo;
|
||||
import android.credentials.ui.UserSelectionDialogResult;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.ResultReceiver;
|
||||
import android.service.credentials.CredentialProviderInfoFactory;
|
||||
@@ -50,6 +51,20 @@ public class CredentialManagerUi {
|
||||
@NonNull private final Context mContext;
|
||||
// TODO : Use for starting the activity for this user
|
||||
private final int mUserId;
|
||||
|
||||
private UiStatus mStatus;
|
||||
|
||||
/** Creates intent that is ot be invoked to cancel an in-progress UI session. */
|
||||
public Intent createCancelIntent(IBinder requestId, String packageName) {
|
||||
return IntentFactory.createCancelUiIntent(requestId, /*shouldShowCancellationUi=*/ true,
|
||||
packageName);
|
||||
}
|
||||
|
||||
enum UiStatus {
|
||||
IN_PROGRESS,
|
||||
USER_INTERACTION,
|
||||
NOT_STARTED, TERMINATED
|
||||
}
|
||||
@NonNull private final ResultReceiver mResultReceiver = new ResultReceiver(
|
||||
new Handler(Looper.getMainLooper())) {
|
||||
@Override
|
||||
@@ -61,6 +76,7 @@ public class CredentialManagerUi {
|
||||
private void handleUiResult(int resultCode, Bundle resultData) {
|
||||
switch (resultCode) {
|
||||
case UserSelectionDialogResult.RESULT_CODE_DIALOG_COMPLETE_WITH_SELECTION:
|
||||
mStatus = UiStatus.IN_PROGRESS;
|
||||
UserSelectionDialogResult selection = UserSelectionDialogResult
|
||||
.fromResultData(resultData);
|
||||
if (selection != null) {
|
||||
@@ -70,16 +86,20 @@ public class CredentialManagerUi {
|
||||
}
|
||||
break;
|
||||
case UserSelectionDialogResult.RESULT_CODE_DIALOG_USER_CANCELED:
|
||||
mStatus = UiStatus.TERMINATED;
|
||||
mCallbacks.onUiCancellation(/* isUserCancellation= */ true);
|
||||
break;
|
||||
case UserSelectionDialogResult.RESULT_CODE_CANCELED_AND_LAUNCHED_SETTINGS:
|
||||
mStatus = UiStatus.TERMINATED;
|
||||
mCallbacks.onUiCancellation(/* isUserCancellation= */ false);
|
||||
break;
|
||||
case UserSelectionDialogResult.RESULT_CODE_DATA_PARSING_FAILURE:
|
||||
mStatus = UiStatus.TERMINATED;
|
||||
mCallbacks.onUiSelectorInvocationFailure();
|
||||
break;
|
||||
default:
|
||||
Slog.i(TAG, "Unknown error code returned from the UI");
|
||||
mStatus = UiStatus.IN_PROGRESS;
|
||||
mCallbacks.onUiSelectorInvocationFailure();
|
||||
break;
|
||||
}
|
||||
@@ -103,6 +123,17 @@ public class CredentialManagerUi {
|
||||
mContext = context;
|
||||
mUserId = userId;
|
||||
mCallbacks = callbacks;
|
||||
mStatus = UiStatus.IN_PROGRESS;
|
||||
}
|
||||
|
||||
/** Set status for credential manager UI */
|
||||
public void setStatus(UiStatus status) {
|
||||
mStatus = status;
|
||||
}
|
||||
|
||||
/** Returns status for credential manager UI */
|
||||
public UiStatus getStatus() {
|
||||
return mStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,12 +45,13 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
|
||||
IGetCredentialCallback, GetCredentialResponse>
|
||||
implements ProviderSession.ProviderInternalCallback<GetCredentialResponse> {
|
||||
private static final String TAG = "GetRequestSession";
|
||||
public GetRequestSession(Context context, int userId, int callingUid,
|
||||
public GetRequestSession(Context context, RequestSession.SessionLifetime sessionCallback,
|
||||
Object lock, int userId, int callingUid,
|
||||
IGetCredentialCallback callback, GetCredentialRequest request,
|
||||
CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal,
|
||||
long startedTimestamp) {
|
||||
super(context, userId, callingUid, request, callback, RequestInfo.TYPE_GET,
|
||||
callingAppInfo, cancellationSignal, startedTimestamp);
|
||||
super(context, sessionCallback, lock, userId, callingUid, request, callback,
|
||||
RequestInfo.TYPE_GET, callingAppInfo, cancellationSignal, startedTimestamp);
|
||||
int numTypes = (request.getCredentialOptions().stream()
|
||||
.map(CredentialOption::getType).collect(
|
||||
Collectors.toSet())).size(); // Dedupe type strings
|
||||
@@ -81,6 +82,7 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
|
||||
@Override
|
||||
protected void launchUiWithProviderData(ArrayList<ProviderData> providerDataList) {
|
||||
mRequestSessionMetric.collectUiCallStartTime(System.nanoTime());
|
||||
mCredentialManagerUi.setStatus(CredentialManagerUi.UiStatus.USER_INTERACTION);
|
||||
try {
|
||||
mClientCallback.onPendingIntent(mCredentialManagerUi.createPendingIntent(
|
||||
RequestInfo.newGetRequestInfo(
|
||||
@@ -88,6 +90,7 @@ public class GetRequestSession extends RequestSession<GetCredentialRequest,
|
||||
providerDataList));
|
||||
} catch (RemoteException e) {
|
||||
mRequestSessionMetric.collectUiReturnedFinalPhase(/*uiReturned=*/ false);
|
||||
mCredentialManagerUi.setStatus(CredentialManagerUi.UiStatus.TERMINATED);
|
||||
respondToClientWithErrorAndFinish(
|
||||
GetCredentialException.TYPE_UNKNOWN, "Unable to instantiate selector");
|
||||
}
|
||||
|
||||
@@ -49,14 +49,13 @@ public class PrepareGetRequestSession extends GetRequestSession {
|
||||
|
||||
private final IPrepareGetCredentialCallback mPrepareGetCredentialCallback;
|
||||
|
||||
public PrepareGetRequestSession(Context context, int userId, int callingUid,
|
||||
IGetCredentialCallback callback,
|
||||
GetCredentialRequest request,
|
||||
CallingAppInfo callingAppInfo,
|
||||
CancellationSignal cancellationSignal, long startedTimestamp,
|
||||
IPrepareGetCredentialCallback prepareGetCredentialCallback) {
|
||||
super(context, userId, callingUid, callback, request, callingAppInfo, cancellationSignal,
|
||||
startedTimestamp);
|
||||
public PrepareGetRequestSession(Context context,
|
||||
RequestSession.SessionLifetime sessionCallback, Object lock, int userId,
|
||||
int callingUid, IGetCredentialCallback getCredCallback, GetCredentialRequest request,
|
||||
CallingAppInfo callingAppInfo, CancellationSignal cancellationSignal,
|
||||
long startedTimestamp, IPrepareGetCredentialCallback prepareGetCredentialCallback) {
|
||||
super(context, sessionCallback, lock, userId, callingUid, getCredCallback, request,
|
||||
callingAppInfo, cancellationSignal, startedTimestamp);
|
||||
int numTypes = (request.getCredentialOptions().stream()
|
||||
.map(CredentialOption::getType).collect(
|
||||
Collectors.toSet())).size(); // Dedupe type strings
|
||||
|
||||
@@ -126,7 +126,8 @@ public final class ProviderClearSession extends ProviderSession<ClearCredentialS
|
||||
protected void invokeSession() {
|
||||
if (mRemoteCredentialService != null) {
|
||||
startCandidateMetrics();
|
||||
mRemoteCredentialService.onClearCredentialState(mProviderRequest, this);
|
||||
mProviderCancellationSignal =
|
||||
mRemoteCredentialService.onClearCredentialState(mProviderRequest, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -236,7 +236,8 @@ public final class ProviderCreateSession extends ProviderSession<
|
||||
protected void invokeSession() {
|
||||
if (mRemoteCredentialService != null) {
|
||||
startCandidateMetrics();
|
||||
mRemoteCredentialService.onCreateCredential(mProviderRequest, this);
|
||||
mProviderCancellationSignal =
|
||||
mRemoteCredentialService.onCreateCredential(mProviderRequest, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -302,7 +302,9 @@ public final class ProviderGetSession extends ProviderSession<BeginGetCredential
|
||||
protected void invokeSession() {
|
||||
if (mRemoteCredentialService != null) {
|
||||
startCandidateMetrics();
|
||||
mRemoteCredentialService.onBeginGetCredential(mProviderRequest, this);
|
||||
mProviderCancellationSignal =
|
||||
mRemoteCredentialService.onBeginGetCredential(mProviderRequest, this);
|
||||
boolean foundSig = mProviderCancellationSignal == null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.credentials.ui.ProviderPendingIntentResponse;
|
||||
import android.os.ICancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.server.credentials.metrics.ProviderSessionMetric;
|
||||
|
||||
@@ -189,7 +190,7 @@ public abstract class ProviderSession<T, R>
|
||||
}
|
||||
setStatus(Status.CANCELED);
|
||||
} catch (RemoteException e) {
|
||||
Log.i(TAG, "Issue while cancelling provider session: " + e.getMessage());
|
||||
Slog.e(TAG, "Issue while cancelling provider session: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.credentials.CredentialProviderInfo;
|
||||
import android.credentials.ui.ProviderData;
|
||||
import android.credentials.ui.UserSelectionDialogResult;
|
||||
@@ -29,8 +30,10 @@ import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
import android.service.credentials.CallingAppInfo;
|
||||
import android.util.Log;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.server.credentials.metrics.ApiName;
|
||||
@@ -39,8 +42,8 @@ import com.android.server.credentials.metrics.ProviderStatusForMetrics;
|
||||
import com.android.server.credentials.metrics.RequestSessionMetric;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Base class of a request session, that listens to UI events. This class must be extended
|
||||
@@ -49,6 +52,11 @@ import java.util.Map;
|
||||
abstract class RequestSession<T, U, V> implements CredentialManagerUi.CredentialManagerUiCallback {
|
||||
private static final String TAG = "RequestSession";
|
||||
|
||||
public interface SessionLifetime {
|
||||
/** Called when the user makes a selection. */
|
||||
void onFinishRequestSession(@UserIdInt int userId, IBinder token);
|
||||
}
|
||||
|
||||
// TODO: Revise access levels of attributes
|
||||
@NonNull
|
||||
protected final T mClientRequest;
|
||||
@@ -72,10 +80,14 @@ abstract class RequestSession<T, U, V> implements CredentialManagerUi.Credential
|
||||
@NonNull
|
||||
protected final CancellationSignal mCancellationSignal;
|
||||
|
||||
protected final Map<String, ProviderSession> mProviders = new HashMap<>();
|
||||
protected final Map<String, ProviderSession> mProviders = new ConcurrentHashMap<>();
|
||||
protected final RequestSessionMetric mRequestSessionMetric = new RequestSessionMetric();
|
||||
protected final String mHybridService;
|
||||
|
||||
protected final Object mLock;
|
||||
|
||||
protected final SessionLifetime mSessionCallback;
|
||||
|
||||
@NonNull
|
||||
protected RequestSessionStatus mRequestSessionStatus =
|
||||
RequestSessionStatus.IN_PROGRESS;
|
||||
@@ -91,11 +103,15 @@ abstract class RequestSession<T, U, V> implements CredentialManagerUi.Credential
|
||||
}
|
||||
|
||||
protected RequestSession(@NonNull Context context,
|
||||
@UserIdInt int userId, int callingUid, @NonNull T clientRequest, U clientCallback,
|
||||
RequestSession.SessionLifetime sessionCallback,
|
||||
Object lock, @UserIdInt int userId, int callingUid,
|
||||
@NonNull T clientRequest, U clientCallback,
|
||||
@NonNull String requestType,
|
||||
CallingAppInfo callingAppInfo,
|
||||
CancellationSignal cancellationSignal, long timestampStarted) {
|
||||
mContext = context;
|
||||
mLock = lock;
|
||||
mSessionCallback = sessionCallback;
|
||||
mUserId = userId;
|
||||
mCallingUid = callingUid;
|
||||
mClientRequest = clientRequest;
|
||||
@@ -111,6 +127,32 @@ abstract class RequestSession<T, U, V> implements CredentialManagerUi.Credential
|
||||
R.string.config_defaultCredentialManagerHybridService);
|
||||
mRequestSessionMetric.collectInitialPhaseMetricInfo(timestampStarted, mRequestId,
|
||||
mCallingUid, ApiName.getMetricCodeFromRequestInfo(mRequestType));
|
||||
setCancellationListener();
|
||||
}
|
||||
|
||||
private void setCancellationListener() {
|
||||
mCancellationSignal.setOnCancelListener(
|
||||
() -> {
|
||||
boolean isUiActive = maybeCancelUi();
|
||||
finishSession(!isUiActive);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private boolean maybeCancelUi() {
|
||||
if (mCredentialManagerUi.getStatus()
|
||||
== CredentialManagerUi.UiStatus.USER_INTERACTION) {
|
||||
final long originalCallingUidToken = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mContext.startActivityAsUser(mCredentialManagerUi.createCancelIntent(
|
||||
mRequestId, mClientAppInfo.getPackageName())
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), UserHandle.of(mUserId));
|
||||
return true;
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(originalCallingUidToken);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public abstract ProviderSession initiateProviderSession(CredentialProviderInfo providerInfo,
|
||||
@@ -154,12 +196,19 @@ abstract class RequestSession<T, U, V> implements CredentialManagerUi.Credential
|
||||
}
|
||||
|
||||
protected void finishSession(boolean propagateCancellation) {
|
||||
Log.i(TAG, "finishing session");
|
||||
Slog.d(TAG, "finishing session with propagateCancellation " + propagateCancellation);
|
||||
if (propagateCancellation) {
|
||||
mProviders.values().forEach(ProviderSession::cancelProviderRemoteSession);
|
||||
}
|
||||
mRequestSessionStatus = RequestSessionStatus.COMPLETE;
|
||||
mProviders.clear();
|
||||
clearRequestSessionLocked();
|
||||
}
|
||||
|
||||
private void clearRequestSessionLocked() {
|
||||
synchronized (mLock) {
|
||||
mSessionCallback.onFinishRequestSession(mUserId, mRequestId);
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isAnyProviderPending() {
|
||||
|
||||
Reference in New Issue
Block a user