1 /*
2  * Copyright (C) 2020 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 android.security.keystore;
18 
19 import android.annotation.DurationMillisLong;
20 import android.annotation.NonNull;
21 
22 import java.security.ProviderException;
23 
24 /**
25  * Indicates a transient error that prevented a key operation from being created.
26  * Callers should try again with a back-off period of {@link #getBackOffHintMillis()}
27  * milliseconds.
28  */
29 public class BackendBusyException extends ProviderException {
30 
31     private final long mBackOffHintMillis;
32 
33     /**
34      * Constructs a new {@code BackendBusyException} without detail message and cause.
35      *
36      */
BackendBusyException(@urationMillisLong long backOffHintMillis)37     public BackendBusyException(@DurationMillisLong long backOffHintMillis) {
38         super("The keystore backend has no operation slots available. Retry later.");
39         if (backOffHintMillis < 0) {
40             throw new IllegalArgumentException("Back-off hint cannot be negative.");
41         }
42         mBackOffHintMillis = backOffHintMillis;
43     }
44 
45     /**
46      * Constructs a new {@code BackendBusyException} with the provided detail message and
47      * no cause.
48      */
BackendBusyException(@urationMillisLong long backOffHintMillis, @NonNull String message)49     public BackendBusyException(@DurationMillisLong long backOffHintMillis,
50             @NonNull String message) {
51         super(message);
52         if (backOffHintMillis < 0) {
53             throw new IllegalArgumentException("Back-off hint cannot be negative.");
54         }
55         mBackOffHintMillis = backOffHintMillis;
56     }
57 
58     /**
59      * Constructs a new {@code BackendBusyException} with the provided detail message and
60      * cause.
61      */
BackendBusyException(@urationMillisLong long backOffHintMillis, @NonNull String message, @NonNull Throwable cause)62     public BackendBusyException(@DurationMillisLong long backOffHintMillis,
63             @NonNull String message, @NonNull Throwable cause) {
64         super(message, cause);
65         if (backOffHintMillis < 0) {
66             throw new IllegalArgumentException("Back-off hint cannot be negative.");
67         }
68         mBackOffHintMillis = backOffHintMillis;
69     }
70 
71     /**
72      * When retrying to start a Keystore operation after receiving this exception, this can be
73      * used to determine how long to wait before retrying. It is not guaranteed that the operation
74      * will succeeds after this time. Multiple retries may be necessary if the system is congested.
75      *
76      * @return Number of milliseconds to back off before retrying.
77      */
getBackOffHintMillis()78     public @DurationMillisLong long getBackOffHintMillis() {
79         return mBackOffHintMillis;
80     }
81 }
82