• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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.ims.rcs.uce.request;
18 
19 import android.net.Uri;
20 import android.telephony.ims.RcsUceAdapter;
21 import android.telephony.ims.RcsContactUceCapability;
22 import android.util.Log;
23 
24 import com.android.ims.rcs.uce.UceDeviceState.DeviceStateResult;
25 import com.android.ims.rcs.uce.eab.EabCapabilityResult;
26 import com.android.ims.rcs.uce.request.UceRequestManager.RequestManagerCallback;
27 import com.android.ims.rcs.uce.util.UceUtils;
28 import com.android.internal.annotations.VisibleForTesting;
29 
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.List;
33 import java.util.Objects;
34 import java.util.stream.Collectors;
35 
36 /**
37  * The base class of the UCE request to request the capabilities from the carrier network.
38  */
39 public abstract class CapabilityRequest implements UceRequest {
40 
41     private static final String LOG_TAG = UceUtils.getLogPrefix() + "CapabilityRequest";
42 
43     protected final int mSubId;
44     protected final long mTaskId;
45     protected final List<Uri> mUriList;
46     protected final @UceRequestType int mRequestType;
47     protected final RequestManagerCallback mRequestManagerCallback;
48     protected final CapabilityRequestResponse mRequestResponse;
49 
50     protected volatile long mCoordinatorId;
51     protected volatile boolean mIsFinished;
52     protected volatile boolean mSkipGettingFromCache;
53 
CapabilityRequest(int subId, @UceRequestType int type, RequestManagerCallback callback)54     public CapabilityRequest(int subId, @UceRequestType int type, RequestManagerCallback callback) {
55         mSubId = subId;
56         mRequestType = type;
57         mUriList = new ArrayList<>();
58         mRequestManagerCallback = callback;
59         mRequestResponse = new CapabilityRequestResponse();
60         mTaskId = UceUtils.generateTaskId();
61     }
62 
63     @VisibleForTesting
CapabilityRequest(int subId, @UceRequestType int type, RequestManagerCallback callback, CapabilityRequestResponse requestResponse)64     public CapabilityRequest(int subId, @UceRequestType int type, RequestManagerCallback callback,
65             CapabilityRequestResponse requestResponse) {
66         mSubId = subId;
67         mRequestType = type;
68         mUriList = new ArrayList<>();
69         mRequestManagerCallback = callback;
70         mRequestResponse = requestResponse;
71         mTaskId = UceUtils.generateTaskId();
72     }
73 
74     @Override
setRequestCoordinatorId(long coordinatorId)75     public void setRequestCoordinatorId(long coordinatorId) {
76         mCoordinatorId = coordinatorId;
77     }
78 
79     @Override
getRequestCoordinatorId()80     public long getRequestCoordinatorId() {
81         return mCoordinatorId;
82     }
83 
84     @Override
getTaskId()85     public long getTaskId() {
86         return mTaskId;
87     }
88 
89     @Override
onFinish()90     public void onFinish() {
91         mIsFinished = true;
92         // Remove the timeout timer of this request
93         mRequestManagerCallback.removeRequestTimeoutTimer(mTaskId);
94     }
95 
96     @Override
setContactUri(List<Uri> uris)97     public void setContactUri(List<Uri> uris) {
98         mUriList.addAll(uris);
99         mRequestResponse.setRequestContacts(uris);
100     }
101 
getContactUri()102     public List<Uri> getContactUri() {
103         return Collections.unmodifiableList(mUriList);
104     }
105 
106     /**
107      * Set to check if this request should be getting the capabilities from the cache. The flag is
108      * set when the request is triggered by the capability polling service. The contacts from the
109      * capability polling service are already expired, skip checking from the cache.
110      */
setSkipGettingFromCache(boolean skipFromCache)111     public void setSkipGettingFromCache(boolean skipFromCache) {
112         mSkipGettingFromCache = skipFromCache;
113     }
114 
115     /**
116      * Return if the capabilities request should skip getting from the cache. The flag is set when
117      * the request is triggered by the capability polling service and the request doesn't need to
118      * check the cache again.
119      */
isSkipGettingFromCache()120     private boolean isSkipGettingFromCache() {
121         return mSkipGettingFromCache;
122     }
123 
124     /**
125      * @return The RequestResponse instance associated with this request.
126      */
getRequestResponse()127     public CapabilityRequestResponse getRequestResponse() {
128         return mRequestResponse;
129     }
130 
131     /**
132      * Start executing this request.
133      */
134     @Override
executeRequest()135     public void executeRequest() {
136         // Return if this request is not allowed to be executed.
137         if (!isRequestAllowed()) {
138             logd("executeRequest: The request is not allowed.");
139             mRequestManagerCallback.notifyRequestError(mCoordinatorId, mTaskId);
140             return;
141         }
142 
143         // Get the capabilities from the cache.
144         final List<RcsContactUceCapability> cachedCapList
145                 = isSkipGettingFromCache() ? Collections.EMPTY_LIST : getCapabilitiesFromCache();
146         mRequestResponse.addCachedCapabilities(cachedCapList);
147 
148         logd("executeRequest: cached capabilities size=" + cachedCapList.size());
149 
150         // Notify that the cached capabilities are updated.
151         if (!cachedCapList.isEmpty()) {
152             mRequestManagerCallback.notifyCachedCapabilitiesUpdated(mCoordinatorId, mTaskId);
153         }
154 
155         // Get the rest contacts which need to request capabilities from the network.
156         final List<Uri> requestCapUris = getRequestingFromNetworkUris(cachedCapList);
157 
158         logd("executeRequest: requestCapUris size=" + requestCapUris.size());
159 
160         // Notify that it doesn't need to request capabilities from the network when all the
161         // requested capabilities can be retrieved from cache. Otherwise, it needs to request
162         // capabilities from the network for those contacts which cannot retrieve capabilities from
163         // the cache.
164         if (requestCapUris.isEmpty()) {
165             mRequestManagerCallback.notifyNoNeedRequestFromNetwork(mCoordinatorId, mTaskId);
166         } else {
167             requestCapabilities(requestCapUris);
168         }
169     }
170 
171     // Check whether this request is allowed to be executed or not.
isRequestAllowed()172     private boolean isRequestAllowed() {
173         if (mUriList == null || mUriList.isEmpty()) {
174             logw("isRequestAllowed: uri is empty");
175             mRequestResponse.setRequestInternalError(RcsUceAdapter.ERROR_GENERIC_FAILURE);
176             return false;
177         }
178 
179         if (mIsFinished) {
180             logw("isRequestAllowed: This request is finished");
181             mRequestResponse.setRequestInternalError(RcsUceAdapter.ERROR_GENERIC_FAILURE);
182             return false;
183         }
184 
185         DeviceStateResult deviceStateResult = mRequestManagerCallback.getDeviceState();
186         if (deviceStateResult.isRequestForbidden()) {
187             logw("isRequestAllowed: The device is disallowed.");
188             mRequestResponse.setRequestInternalError(
189                     deviceStateResult.getErrorCode().orElse(RcsUceAdapter.ERROR_GENERIC_FAILURE));
190             return false;
191         }
192         return true;
193     }
194 
195     // Get the cached capabilities by the given request type.
getCapabilitiesFromCache()196     private List<RcsContactUceCapability> getCapabilitiesFromCache() {
197         List<EabCapabilityResult> resultList = null;
198         if (mRequestType == REQUEST_TYPE_CAPABILITY) {
199             resultList = mRequestManagerCallback.getCapabilitiesFromCache(mUriList);
200         } else if (mRequestType == REQUEST_TYPE_AVAILABILITY) {
201             // Always get the first element if the request type is availability.
202             Uri uri = mUriList.get(0);
203             EabCapabilityResult eabResult = mRequestManagerCallback.getAvailabilityFromCache(uri);
204             resultList = new ArrayList<>();
205             resultList.add(eabResult);
206         }
207         if (resultList == null) {
208             return Collections.emptyList();
209         }
210         return resultList.stream()
211                 .filter(Objects::nonNull)
212                 .filter(result -> result.getStatus() == EabCapabilityResult.EAB_QUERY_SUCCESSFUL)
213                 .map(EabCapabilityResult::getContactCapabilities)
214                 .filter(Objects::nonNull)
215                 .collect(Collectors.toList());
216     }
217 
218     /**
219      * Get the contact uris which cannot retrieve capabilities from the cache.
220      * @param cachedCapList The capabilities which are already stored in the cache.
221      */
getRequestingFromNetworkUris(List<RcsContactUceCapability> cachedCapList)222     private List<Uri> getRequestingFromNetworkUris(List<RcsContactUceCapability> cachedCapList) {
223         return mUriList.stream()
224                 .filter(uri -> cachedCapList.stream()
225                         .noneMatch(cap -> cap.getContactUri().equals(uri)))
226                         .collect(Collectors.toList());
227     }
228 
229     /**
230      * Set the timeout timer of this request.
231      */
setupRequestTimeoutTimer()232     protected void setupRequestTimeoutTimer() {
233         long timeoutAfterMs = UceUtils.getCapRequestTimeoutAfterMillis();
234         logd("setupRequestTimeoutTimer(ms): " + timeoutAfterMs);
235         mRequestManagerCallback.setRequestTimeoutTimer(mCoordinatorId, mTaskId, timeoutAfterMs);
236     }
237 
238     /*
239      * Requests capabilities from IMS. The inherited request is required to override this method
240      * to define the behavior of requesting capabilities.
241      */
requestCapabilities(List<Uri> requestCapUris)242     protected abstract void requestCapabilities(List<Uri> requestCapUris);
243 
logd(String log)244     protected void logd(String log) {
245         Log.d(LOG_TAG, getLogPrefix().append(log).toString());
246     }
247 
logw(String log)248     protected void logw(String log) {
249         Log.w(LOG_TAG, getLogPrefix().append(log).toString());
250     }
251 
logi(String log)252     protected void logi(String log) {
253         Log.i(LOG_TAG, getLogPrefix().append(log).toString());
254     }
255 
getLogPrefix()256     private StringBuilder getLogPrefix() {
257         StringBuilder builder = new StringBuilder("[");
258         builder.append(mSubId).append("][taskId=").append(mTaskId).append("] ");
259         return builder;
260     }
261 }
262