1 /*
2  * Copyright (C) 2023 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.adservices.exceptions;
18 
19 import static java.util.Locale.ENGLISH;
20 
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 
27 /**
28  * Exception thrown by the service when a failed HTTP request is the cause of a failed API call.
29  *
30  * @hide
31  */
32 public class AdServicesNetworkException extends AdServicesException {
33     /**
34      * Error code indicating that the service received an <a
35      * href="https://httpwg.org/specs/rfc9110.html#status.3xx">HTTP 3xx</a> status code.
36      */
37     public static final int ERROR_REDIRECTION = 3;
38 
39     /**
40      * Error code indicating that the service received an <a
41      * href="https://httpwg.org/specs/rfc9110.html#status.4xx">HTTP 4xx</a> status code.
42      */
43     public static final int ERROR_CLIENT = 4;
44 
45     /**
46      * Error code indicating that the user has sent too many requests in a given amount of time and
47      * the service received an <a href="https://httpwg.org/specs/rfc6585.html#status-429">HTTP
48      * 429</a> status code.
49      */
50     public static final int ERROR_TOO_MANY_REQUESTS = 429;
51 
52     /**
53      * Error code indicating that the service received an <a
54      * href="https://httpwg.org/specs/rfc9110.html#status.4xx">HTTP 5xx</a> status code.
55      */
56     public static final int ERROR_SERVER = 5;
57 
58     /** Error code indicating another type of error was encountered. */
59     public static final int ERROR_OTHER = 999;
60 
61     /** Error codes indicating what caused the HTTP request to fail. */
62     @IntDef(
63             prefix = {"ERROR_"},
64             value = {
65                 ERROR_REDIRECTION,
66                 ERROR_CLIENT,
67                 ERROR_TOO_MANY_REQUESTS,
68                 ERROR_SERVER,
69                 ERROR_OTHER
70             })
71     @Retention(RetentionPolicy.SOURCE)
72     public @interface ErrorCode {}
73 
74     /** @hide */
75     public static final String INVALID_ERROR_CODE_MESSAGE = "Valid error code must be set.";
76 
77     @ErrorCode private final int mErrorCode;
78 
79     /**
80      * Constructs an {@link AdServicesNetworkException} that is caused by a failed HTTP request.
81      *
82      * @param errorCode relevant {@link ErrorCode} corresponding to the failure.
83      */
AdServicesNetworkException(@rrorCode int errorCode)84     public AdServicesNetworkException(@ErrorCode int errorCode) {
85         super();
86 
87         checkErrorCode(errorCode);
88         mErrorCode = errorCode;
89     }
90 
91     /**
92      * @return the {@link ErrorCode} indicating what caused the HTTP request to fail.
93      */
94     @NonNull
95     @ErrorCode
getErrorCode()96     public int getErrorCode() {
97         return mErrorCode;
98     }
99 
100     /**
101      * @return a human-readable representation of {@link AdServicesNetworkException}.
102      */
103     @Override
toString()104     public String toString() {
105         return String.format(
106                 ENGLISH,
107                 "%s: {Error code: %s}",
108                 this.getClass().getCanonicalName(),
109                 this.getErrorCode());
110     }
111 
checkErrorCode(@rrorCode int errorCode)112     private void checkErrorCode(@ErrorCode int errorCode) {
113         switch (errorCode) {
114             case ERROR_REDIRECTION:
115                 // Intentional fallthrough
116             case ERROR_CLIENT:
117                 // Intentional fallthrough
118             case ERROR_TOO_MANY_REQUESTS:
119                 // Intentional fallthrough
120             case ERROR_SERVER:
121                 // Intentional fallthrough
122             case ERROR_OTHER:
123                 break;
124             default:
125                 throw new IllegalArgumentException(INVALID_ERROR_CODE_MESSAGE);
126         }
127     }
128 }
129