Unit 3 - Practice Quiz

CSE227 60 Questions
0 Correct 0 Wrong 60 Left
0/60

1 What is Retrofit primarily used for in Android development?

Retrofit Basics and Integration Easy
A. Type-safe HTTP client for Android and Java
B. Managing device hardware like the camera
C. Database management
D. UI design and layout

2 Which company is the creator of the Retrofit library?

Retrofit Basics and Integration Easy
A. Microsoft
B. Square
C. Facebook
D. Google

3 What is the main purpose of the Retrofit.Builder class?

Retrofit Basics and Integration Easy
A. To parse JSON data directly
B. To construct a Retrofit instance with specific configurations
C. To manage Android permissions for networking
D. To create UI components for displaying data

4 To integrate Retrofit into a Gradle-based Android project, which section of the build.gradle file do you add its dependency to?

Retrofit Basics and Integration Easy
A. plugins
B. repositories
C. android
D. dependencies

5 In Retrofit, what does the @GET annotation signify?

Handling API Requests Easy
A. It gets a user's current GPS location.
B. It retrieves data from a local SQLite database.
C. It generates a new Kotlin class.
D. It specifies that the request is an HTTP GET request.

6 How are API endpoints defined in Retrofit?

Handling API Requests Easy
A. Inside a plain text file in the assets folder
B. Inside the AndroidManifest.xml file
C. Inside an XML layout file
D. Inside a Java or Kotlin interface using annotations

7 What is the purpose of the @Path annotation in a Retrofit interface method?

Handling API Requests Easy
A. To define the entire base URL for the request
B. To specify the content of the request body
C. To add a query parameter to the end of the URL
D. To replace a placeholder in the URL path with a dynamic value

8 If you want to add a URL parameter like ?sort=new, which Retrofit annotation would you use?

Handling API Requests Easy
A. @Header
B. @Query
C. @Body
D. @Path

9 Which of the following is a popular JSON parsing library often used with Retrofit as a converter?

Parsing and Displaying Data Easy
A. Gson
B. Room
C. Picasso
D. Glide

10 In the context of using Retrofit with a JSON API, what is the role of a data class (or POJO)?

Parsing and Displaying Data Easy
A. To model the structure of the expected JSON response
B. To define the API endpoints and methods
C. To handle background threading for network calls
D. To create the user interface layout

11 What is the purpose of GsonConverterFactory.create() when building a Retrofit instance?

Parsing and Displaying Data Easy
A. To tell Retrofit to use Gson for JSON serialization and deserialization
B. To enable logging of network requests and responses
C. To specify the base URL for the API
D. To add HTTP headers to every request

12 Which Android UI component is most commonly used to display a list of items fetched from an API?

Parsing and Displaying Data Easy
A. ImageView
B. RecyclerView
C. TextView
D. Button

13 To automatically parse a JSON object into a Kotlin data class, the variable names in the data class should typically match what?

Parsing and Displaying Data Easy
A. The names of the API methods in the interface
B. The XML attribute names in the layout file
C. The file names in the project's res folder
D. The keys in the JSON object

14 Which method on a Retrofit Call object is used to execute a network request asynchronously?

Asynchronous Networking Easy
A. execute()
B. run()
C. enqueue()
D. cancel()

15 What is the main reason for making network requests asynchronously in an Android app?

Asynchronous Networking Easy
A. It always makes the network connection faster.
B. It makes the code shorter and easier to write.
C. It automatically retries failed requests.
D. It prevents the UI thread from blocking, avoiding an 'Application Not Responding' (ANR) error.

16 When using Kotlin Coroutines with Retrofit, what keyword is added to an interface method to make it a non-blocking function?

Asynchronous Networking Easy
A. await
B. launch
C. suspend
D. async

17 What is the most common and scalable way to add a dynamic authentication token to every request made with Retrofit?

Authentication Easy
A. Manually add the token as a parameter to every API method
B. Use an OkHttp Interceptor to add an Authorization header
C. Store the token in an XML resource file
D. Embed the token directly into the base URL

18 Which HTTP header is conventionally used to send an API token for authentication, often prefixed with "Bearer"?

Authentication Easy
A. Accept
B. Content-Type
C. User-Agent
D. Authorization

19 In a Retrofit API interface, the @Header annotation is used for what purpose?

Authentication Easy
A. To define the entire request body as a header
B. To parse the response headers from the server
C. To add a static HTTP header to a specific request
D. To replace a part of the URL with a header value

20 Which annotation is used to send a complete object as the request body, typically for an HTTP POST or PUT request?

Handling API Requests Easy
A. @Body
B. @Query
C. @Field
D. @Path

21 When configuring a Retrofit.Builder, you add multiple Converter.Factory instances, first GsonConverterFactory and then MoshiConverterFactory. Which converter will Retrofit attempt to use first for response parsing?

Retrofit Basics and Integration Medium
A. The one added last (MoshiConverterFactory).
B. The one added first (GsonConverterFactory).
C. Retrofit will throw an IllegalStateException at build time.
D. Retrofit randomly selects one for each request.

22 You are setting up a Retrofit instance. Consider the following code:
kotlin
val retrofit = Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.build()
val apiService = retrofit.create(ApiService::class.java)

What essential component is missing for this instance to make a successful network request to https://api.example.com/users?

Retrofit Basics and Integration Medium
A. An OkHttpClient.
B. A CallAdapter.Factory.
C. A baseUrl().
D. An Executor.

23 In the context of Retrofit, what is the primary role of defining an interface with annotations like @GET and @POST?

Retrofit Basics and Integration Medium
A. To serve as a declarative specification of the API endpoints, which Retrofit uses to generate the actual network request code at runtime.
B. To directly manage threading and background execution for network calls.
C. To define callback methods for handling asynchronous responses.
D. To provide a concrete implementation of how to perform HTTP requests.

24 Why would a developer explicitly provide a custom OkHttpClient to the Retrofit.Builder using .client(myOkHttpClient)?

Retrofit Basics and Integration Medium
A. To change the base URL for different environments.
B. To configure advanced features like setting timeouts, adding interceptors for logging or authentication, and managing caching.
C. To specify the JSON parsing library (like Gson or Moshi).
D. Because Retrofit cannot make network calls without a custom OkHttpClient.

25 Given the Retrofit interface method:
kotlin
@GET("group/{id}/users")
fun groupList(@Path("id") groupId: Int, @Query("sort") sort: String): Call<List<User>>

If you call this method with groupList(42, "desc"), what will be the resulting relative URL?

Handling API Requests Medium
A. group/42/users&sort=desc
B. group/users/42?sort=desc
C. group/42/users?sort=desc
D. group/{id}/users?groupId=42&sort=desc

26 When sending data in the body of a POST request, what is the key difference between using the @Body and @Field annotations in a Retrofit interface?

Handling API Requests Medium
A. @Body sends a single object serialized as the request body (e.g., as JSON), while @Field is used for sending individual form-urlencoded key-value pairs.
B. @Body and @Field are interchangeable and achieve the same result.
C. @Field is for JSON objects, and @Body is for raw text.
D. @Body can only be used with GET requests, whereas @Field is for POST requests.

27 Your app needs to send a unique, dynamically generated X-Request-ID header with each API call. Which Retrofit annotation is the most appropriate for this purpose when the ID changes for every call?

Handling API Requests Medium
A. @Header as a method parameter.
B. @Headers at the method level.
C. @HeaderMap as a method parameter.
D. @Path as a method parameter.

28 You need to make a POST request to an endpoint that expects data in application/x-www-form-urlencoded format. Which combination of annotations is required on your Retrofit interface method?

Handling API Requests Medium
A. @PUT, @Multipart, and @Part.
B. @POST and @QueryMap.
C. @POST and @Body.
D. @POST, @FormUrlEncoded, and one or more @Field annotations.

29 If you use the @Url annotation in a Retrofit interface method parameter, what is a key requirement for the endpoint definition in the annotation (e.g., @GET)?

Handling API Requests Medium
A. The @GET annotation's value must be empty.
B. The @GET annotation must contain a full URL.
C. The method must also include a @Path annotation.
D. The @GET annotation must define at least one path parameter.

30 You are using GsonConverterFactory and your API returns a JSON object. If a field exists in the JSON response but is not defined in your corresponding Kotlin data class, what is the default behavior of Gson?

Parsing and Displaying Data Medium
A. The field will be ignored, and parsing will continue successfully for the other fields.
B. Gson will throw a NullPointerException when trying to create the object.
C. The call will fail and the onFailure callback will be triggered.
D. The app will crash with a JsonParseException.

31 The API returns a JSON with a field named "first_name". Your Kotlin data class has a property named firstName. How can you correctly map this field using Gson without changing the property name in your data class?

Parsing and Displaying Data Medium
A. Create a custom TypeAdapter.
B. Use the @SerializedName("first_name") annotation on the firstName property.
C. Use the @Field("first_name") annotation on the firstName property.
D. This mapping is done automatically by Gson if you configure it with a specific field naming policy.

32 An API endpoint /users returns a JSON array of user objects, like [ { "id": 1, "name": "Alice" }, { "id": 2, "name": "Bob" } ]. What should be the return type of the corresponding method in your Retrofit interface?

Parsing and Displaying Data Medium
A. Call<User[]>
B. Call<List<User>>
C. Call<Map<String, User>>
D. Call<User>

33 What is the most appropriate use case for creating a custom Gson TypeAdapter and registering it with your Retrofit instance?

Parsing and Displaying Data Medium
A. When the API returns a standard date format like "2023-10-27T10:00:00Z".
B. When you need to map JSON keys with underscores to camelCase property names.
C. When you need to parse a JSON field that can be either a single object or an array of objects into a consistent list format.
D. When you need to change the base URL of your API requests dynamically.

34 In Retrofit, which statement correctly compares call.execute() and call.enqueue()?

Asynchronous Networking Medium
A. execute() is synchronous and blocks the current thread, so it must be called from a background thread. enqueue() is asynchronous and safely executes the request on a background thread, delivering results to the main thread via callbacks.
B. execute() is asynchronous and should be used on the main thread; enqueue() is synchronous and must be used on a background thread.
C. execute() returns a Response object directly, while enqueue() returns void.
D. Both are asynchronous, but enqueue() allows for cancellation while execute() does not.

35 What is the primary advantage of defining a Retrofit service method as a suspend fun for use with Kotlin Coroutines, compared to the traditional Call<T> with enqueue()?

Asynchronous Networking Medium
A. It allows for synchronous network calls on the main thread.
B. It automatically retries failed network requests.
C. It provides more detailed error responses from the server.
D. It allows writing asynchronous code in a sequential, non-blocking manner, which simplifies error handling and avoids "callback hell".

36 When using call.enqueue(callback), if the server responds with an HTTP status code of 404 (Not Found), which part of the Callback will be executed?

Asynchronous Networking Medium
A. The onResponse() method, where response.body() will be null and isSuccessful() will be true.
B. The onResponse() method, where response.isSuccessful() will be false.
C. The onFailure() method, with an HttpException.
D. The onFailure() method, with an IOException.

37 When using a suspend function in a Retrofit interface, how should you handle potential network errors like a timeout or no internet connectivity?

Asynchronous Networking Medium
A. By checking response.isSuccessful() after the call.
B. The coroutine will automatically handle it and return a null value.
C. By wrapping the suspend function call in a try-catch block and catching IOException or other relevant exceptions.
D. Retrofit's coroutine support converts network errors into non-fatal exceptions that can be ignored.

38 What is the most common and maintainable way to add an Authorization: Bearer <token> header to every request made through a single Retrofit instance?

Authentication Medium
A. Creating an OkHttp Interceptor that adds the header to each outgoing request.
B. Appending the token as a query parameter in the baseUrl.
C. Storing the token in a singleton and manually constructing the header before each call.
D. Adding an @Header("Authorization") parameter to every single method in your API interface.

39 Your application uses an OAuth 2.0 access token that expires. When a request fails with a 401 Unauthorized error, you need to use a refresh token to get a new access token and then retry the original request. Which OkHttp component is best suited for implementing this logic?

Authentication Medium
A. A standard network Interceptor.
B. An Authenticator.
C. A custom Converter.Factory.
D. A CallAdapter.Factory.

40 You need to add a static API key as a query parameter (e.g., ?api_key=YOUR_KEY) to all requests made by Retrofit. Which is the most efficient and cleanest approach?

Authentication Medium
A. Manually build the URL with the key before passing it to Retrofit using the @Url annotation.
B. Add @Query("api_key") apiKey: String to every interface method.
C. Use an OkHttp Interceptor to intercept the request, retrieve its URL, and append the new query parameter.
D. Define a constant in your interface and concatenate it to the path of every @GET annotation.

41 You have configured a Retrofit instance with two custom Converter.Factory implementations, FactoryA and FactoryB, added in that order: retrofitBuilder.addConverterFactory(FactoryA).addConverterFactory(FactoryB). FactoryA can handle TypeX but returns null from its responseBodyConverter method for TypeY. FactoryB can handle TypeY. If you make an API call defined as fun getData(): Call<TypeY>, what will be the outcome?

Retrofit Basics and Integration Hard
A. The call will fail with an IllegalArgumentException because FactoryA was checked first and couldn't handle TypeY.
B. Retrofit will skip FactoryA since it returned null for TypeY and will successfully use FactoryB to convert the response.
C. Retrofit will throw a custom exception at build time indicating a converter conflict for TypeY.
D. The application will crash with a NullPointerException when Retrofit attempts to use the null converter returned by FactoryA.

42 In a multithreaded application, multiple concurrent API calls fail with a 401 Unauthorized error, triggering your custom Retrofit Authenticator. A naive implementation of the authenticate() method immediately calls the token refresh endpoint. What is the primary race condition this approach creates, and what is the correct way to solve it?

Authentication Hard
A. The race condition is that the server might invalidate all sessions; solve by adding a random delay before each refresh attempt.
B. The race condition is a deadlock in the OkHttp dispatcher; solve by using a separate OkHttpClient for the refresh call.
C. The race condition is that the old token might be used by a new request before it's refreshed; solve by clearing all tokens first.
D. The race condition is making multiple, redundant token refresh requests; solve by using a synchronized block to ensure only one thread refreshes the token while others wait for the result.

43 Consider the following Kotlin Coroutines code within a ViewModel: viewModelScope.launch { val userDeferred = async { api.getUser() }; val postsDeferred = async { api.getPosts() }; try { val user = userDeferred.await(); val posts = postsDeferred.await(); } catch (e: Exception) { // handle error } }. If the api.getPosts() call fails with an IOException but api.getUser() completes successfully before the failure, what is the state of the viewModelScope's Job and what happens to the result of api.getUser()?

Asynchronous Networking Hard
A. The parent Job remains active, the exception is caught, and the user variable will hold the valid user data.
B. The entire viewModelScope crashes, and the application must be restarted to recover.
C. Both async blocks are independent; userDeferred.await() will succeed, and only postsDeferred.await() will throw, allowing partial data processing.
D. The parent Job is cancelled, and the result of getUser() is lost as the try-catch block catches the exception from the failing await().

44 You need to implement a file upload using a @Multipart request. The API requires a JSON object and a file to be sent in the same request. How should you define the RequestBody for the JSON part to ensure it is correctly formatted with Content-Type: application/json?

Handling API Requests Hard
A. Annotate the data class with @Multipart: @Part("data") data: MyDataClass
B. Retrofit automatically handles this if you use a Gson converter and pass the data class object: @Part("data") data: MyDataClass
C. Use a generic RequestBody: @Part("data") data: RequestBody where the body is created with RequestBody.create("application/json; charset=utf-8".toMediaType(), jsonString)
D. Pass the JSON string directly: @Part("data") data: String

45 An API endpoint returns a JSON array of 'events'. Each event object has a "type" field ("message" or "image") and other fields that differ based on the type. How would you model this polymorphic data using Moshi and a custom JsonAdapter.Factory for seamless parsing into a sealed class Event?

Parsing and Displaying Data Hard
A. Use @JsonClass(generator = "sealed:type") on the sealed class and @Json(name = ...) on the subclasses to automatically delegate parsing based on the "type" field.
B. Manually parse the JSON string in the ViewModel by checking the "type" field for each element.
C. Create a single large data class with all possible fields as nullable and use @Json(name = ...).
D. Use a generic Map<String, Any> to receive the data and then manually cast it based on the "type" field.

46 You have implemented a Retrofit Authenticator to refresh a JWT. The token refresh endpoint itself is protected and requires the expired token to be passed for validation. What critical step must you take when creating the OkHttpClient for the refresh API call inside the authenticate() method to avoid an infinite loop?

Authentication Hard
A. The refresh call must be synchronous using .execute() instead of .enqueue().
B. You must add a special header to the refresh request, e.g., "X-Is-Refresh-Call: true", which the Authenticator checks to ignore 401s.
C. Both B and C are valid strategies, but using a separate OkHttpClient is the cleaner, recommended approach.
D. You must use a separate OkHttpClient instance for the refresh call that does not have the Authenticator attached.

47 A Retrofit service method is defined with a dynamic URL: suspend fun getFile(@Url fileUrl: String): ResponseBody. The base URL of the Retrofit instance is https://api.example.com/v1/. If you call this method with getFile("images/logo.png"), what will be the final request URL, and why?

Retrofit Basics and Integration Hard
A. images/logo.png - The @Url parameter completely overrides the base URL, leading to an invalid request.
B. https://api.example.com/images/logo.png - The relative path is resolved against the host of the base URL, ignoring its path segments.
C. https://api.example.com/v1/images/logo.png - The relative path is resolved against the base URL.
D. The call will fail with an IllegalArgumentException because a full, absolute URL is required for @Url.

48 When defining a Retrofit service interface with suspend functions, what is the fundamental difference in error handling between a function returning Response<T> versus one returning just T when the server responds with an HTTP error code like 404 or 500?

Asynchronous Networking Hard
A. Both will throw an HttpException, but with Response<T> you can inspect the error body before it throws.
B. Returning T throws an HttpException which must be caught, while Response<T> returns a response object with isSuccessful = false and does not throw.
C. Returning T will result in a null value for the object, while Response<T> will contain an error code.
D. There is no difference; both scenarios must be wrapped in a try-catch block to handle network failures.

49 An API requires you to send a DELETE request with a JSON body. Which combination of Retrofit annotations would you use to define this service method?

Handling API Requests Hard
A. @HTTP(method = "DELETE", path = "items/{id}", hasBody = true) and @Body body: RequestBody
B. @DELETE does not support a request body; you must use @POST and a custom header like X-HTTP-Method-Override: DELETE.
C. @DELETE("items/{id}") and @Body body: RequestBody
D. @FormUrlEncoded and @DELETE("items/{id}") with @Field annotations for the body.

50 An API for a specific field sometimes returns a JSON object {"key":"value"} and other times returns an empty JSON array [] to signify 'no data'. A standard Gson/Moshi parser would crash with a type mismatch. What is the most robust way to handle this using a custom adapter?

Parsing and Displaying Data Hard
A. Write a custom JsonAdapter that, in its fromJson method, checks the next token. If it's BEGIN_ARRAY, it consumes the array and returns a null or default object. If it's BEGIN_OBJECT, it proceeds with normal object parsing.
B. Define the field as Any in your data class and perform instanceof checks at runtime.
C. Use two separate Retrofit service methods, one for each expected return type, and call the appropriate one based on context.
D. Pre-process the raw JSON string using an OkHttp Interceptor to replace [] with null before it reaches the parser.

51 What is the primary purpose of a Retrofit CallAdapter.Factory, and in which scenario is creating a custom one absolutely necessary?

Retrofit Basics and Integration Hard
A. To control the threading of network requests, switching between background and main threads. It is necessary for all UI updates.
B. To convert response bodies from JSON/XML to Java/Kotlin objects. It's necessary for handling custom data formats.
C. To add custom headers, like for authentication, to every outgoing request. It's necessary for implementing OAuth2.
D. To adapt the standard Call<T> object into another type, such as Single<T> for RxJava or a custom Result<T> wrapper. It's necessary when not using Call or coroutine suspend functions.

52 If your Authenticator's authenticate() method returns null, what is the direct consequence for the original request that received the 401 and for any other requests that were queued by OkHttp while the authenticator was running?

Authentication Hard
A. Only the original request is cancelled; the queued requests are attempted with the old token.
B. The authenticator will be called again for the same request, creating an infinite loop.
C. Retrofit re-throws the 401 error as an HttpException, which can be caught by the application.
D. The original request and all queued requests are immediately cancelled, and the call chain is terminated for all of them.

53 Consider a Retrofit method: fun search(@Query("q") query: String?, @Query("sort") sort: String = "asc"). How does Retrofit handle a null value passed for the query parameter, and how does it handle the default value for the sort parameter if it's not provided by the caller?

Handling API Requests Hard
A. The URL will include q= (an empty value) for the null query. The sort parameter will be omitted if not specified.
B. Both parameters will be omitted from the URL if their values are null or the default, respectively.
C. The parameter q will be omitted from the URL if its value is null. The sort parameter will be included with the value "asc" if not specified.
D. It will throw a NullPointerException for the null query. Default values are not supported and must be passed explicitly.

54 When using the Gson converter, you have a data class with a lateinit var property. The corresponding field is missing from the JSON response. What will be the outcome during deserialization?

Parsing and Displaying Data Hard
A. The deserialization will fail immediately with a JsonSyntaxException because a non-nullable property could not be set.
B. Gson will skip the field, and the property will remain uninitialized, causing an UninitializedPropertyAccessException only when it's accessed.
C. Gson will assign null to the property, causing an UninitializedPropertyAccessException when it's accessed later.
D. Gson will instantiate the property with a default value (e.g., empty string for String).

55 You are using Flow with Retrofit to implement a real-time search feature. A code snippet in your ViewModel is: searchQuery.debounce(300).flatMapLatest { query -> flow { emit(api.search(query)) } }.catch { ... }. If a user types quickly, causing a new query to be emitted while a previous api.search() call is still in flight, what does flatMapLatest ensure?

Asynchronous Networking Hard
A. It cancels the ongoing network request from the previous query and starts a new one for the latest query.
B. It queues the new network request to be executed only after the current one finishes.
C. It ignores the new query until the current network request is complete, effectively throttling the input.
D. It runs all network requests in parallel and merges the results in the order they complete.

56 If you add a HttpLoggingInterceptor as a network interceptor (addNetworkInterceptor) versus an application interceptor (addInterceptor), how does the logged Request object differ when a request is redirected by the server (e.g., a 301 response)?

Retrofit Basics and Integration Hard
A. The application interceptor logs only the initial request to the original URL. The network interceptor will be invoked multiple times, logging the request to the original URL and then the subsequent request to the redirected URL.
B. The application interceptor logs the entire chain of requests. The network interceptor logs only the final successful request.
C. The network interceptor logs only the final request to the redirected URL. The application interceptor logs only the initial request.
D. There is no difference; both will log the same initial request.

57 What is the key difference between using @QueryMap with a Map<String, String> and using multiple @Query annotations in a Retrofit service method?

Handling API Requests Hard
A. @QueryMap is for POST requests while @Query is for GET requests.
B. @QueryMap allows for a dynamic number of query parameters to be added at runtime, whereas @Query is for a fixed, known set of parameters defined in the method signature.
C. There is no functional difference; @QueryMap is just syntactic sugar for multiple @Query annotations.
D. @Query parameters are URL-encoded, but @QueryMap parameters are not.

58 When securing API keys used by your Retrofit/OkHttp client in an Android app, which method provides the strongest protection against static analysis and reverse engineering of the APK?

Authentication Hard
A. Storing the key as an encrypted string in strings.xml and decrypting it at runtime.
B. Obfuscating the key in Kotlin/Java code using tools like ProGuard/R8.
C. Storing the key in a native C/C++ library using the NDK and retrieving it via JNI calls.
D. Storing the key in build.gradle and accessing it via BuildConfig.API_KEY.

59 You make a suspend Retrofit call inside a coroutine launched with supervisorScope. If the network call fails with an IOException, how does this exception affect the supervisorScope and its other child coroutines?

Asynchronous Networking Hard
A. The exception is contained within the failing child coroutine, which is cancelled, but the supervisorScope and its other children continue to run unaffected.
B. The exception cancels the supervisorScope and all its children immediately.
C. The exception propagates up, crashing the application unless caught outside the supervisorScope.
D. The supervisorScope re-launches the failed coroutine automatically.

60 When building an OkHttpClient, you can set timeouts using connectTimeout, readTimeout, and callTimeout. If you set a callTimeout of 30 seconds and a readTimeout of 15 seconds, and a server takes 20 seconds to send a response, what will happen?

Retrofit Basics and Integration Hard
A. The timers will conflict, causing an IllegalStateException when the client is built.
B. The request will fail with a SocketTimeoutException because the readTimeout of 15 seconds was exceeded.
C. The request will succeed because the total time (20s) is less than the callTimeout (30s).
D. The request will fail with an exception related to the callTimeout because it is the overarching limit.