• 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 static com.android.ims.rcs.uce.util.NetworkSipCode.SIP_CODE_SERVER_INTERNAL_ERROR;
20 import static com.android.ims.rcs.uce.util.NetworkSipCode.SIP_SERVICE_UNAVAILABLE;
21 
22 import android.os.RemoteException;
23 import android.telephony.ims.RcsContactUceCapability;
24 import android.telephony.ims.aidl.IOptionsRequestCallback;
25 
26 import com.android.ims.rcs.uce.request.RemoteOptionsRequest.RemoteOptResponse;
27 import com.android.ims.rcs.uce.request.UceRequestManager.RequestManagerCallback;
28 import com.android.ims.rcs.uce.UceStatsWriter;
29 import com.android.internal.annotations.VisibleForTesting;
30 
31 import java.util.Collection;
32 
33 /**
34  * Responsible for the manager the remote options request and triggering the callback to notify
35  * the result of the request.
36  */
37 public class RemoteOptionsCoordinator extends UceRequestCoordinator {
38     /**
39      * The builder of the RemoteOptionsCoordinator.
40      */
41     public static final class Builder {
42         RemoteOptionsCoordinator mRemoteOptionsCoordinator;
43 
Builder(int subId, Collection<UceRequest> requests, RequestManagerCallback c)44         public Builder(int subId, Collection<UceRequest> requests, RequestManagerCallback c) {
45             mRemoteOptionsCoordinator = new RemoteOptionsCoordinator(subId, requests, c,
46                     UceStatsWriter.getInstance());
47         }
48         @VisibleForTesting
Builder(int subId, Collection<UceRequest> requests, RequestManagerCallback c, UceStatsWriter instance)49         public Builder(int subId, Collection<UceRequest> requests, RequestManagerCallback c,
50                 UceStatsWriter instance) {
51             mRemoteOptionsCoordinator = new RemoteOptionsCoordinator(subId, requests, c, instance);
52         }
53 
setOptionsRequestCallback(IOptionsRequestCallback callback)54         public Builder setOptionsRequestCallback(IOptionsRequestCallback callback) {
55             mRemoteOptionsCoordinator.setOptionsRequestCallback(callback);
56             return this;
57         }
58 
build()59         public RemoteOptionsCoordinator build() {
60             return mRemoteOptionsCoordinator;
61         }
62     }
63 
64     /**
65      * Different request updated events will create different {@link RequestResult}. Define the
66      * interface to get the {@link RequestResult} instance according to the given task ID and
67      * {@link RemoteOptResponse}.
68      */
69     @FunctionalInterface
70     private interface RequestResultCreator {
createRequestResult(long taskId, RemoteOptResponse response)71         RequestResult createRequestResult(long taskId, RemoteOptResponse response);
72     }
73 
74     // The RequestResult creator of the remote options response.
75     private static final RequestResultCreator sRemoteResponseCreator = (taskId, response) -> {
76         RcsContactUceCapability capability = response.getRcsContactCapability();
77         if (capability != null) {
78             return RequestResult.createSuccessResult(taskId);
79         } else {
80             int errorCode = response.getErrorSipCode().orElse(SIP_CODE_SERVER_INTERNAL_ERROR);
81             return RequestResult.createFailedResult(taskId, errorCode, 0L);
82         }
83     };
84 
85     // The callback to notify the result of the remote options request.
86     private IOptionsRequestCallback mOptionsReqCallback;
87 
88     private final UceStatsWriter mUceStatsWriter;
89 
RemoteOptionsCoordinator(int subId, Collection<UceRequest> requests, RequestManagerCallback requestMgrCallback, UceStatsWriter instance)90     private RemoteOptionsCoordinator(int subId, Collection<UceRequest> requests,
91             RequestManagerCallback requestMgrCallback, UceStatsWriter instance) {
92         super(subId, requests, requestMgrCallback);
93         mUceStatsWriter = instance;
94         logd("RemoteOptionsCoordinator: created");
95     }
96 
setOptionsRequestCallback(IOptionsRequestCallback callback)97     public void setOptionsRequestCallback(IOptionsRequestCallback callback) {
98         mOptionsReqCallback = callback;
99     }
100 
101     @Override
onFinish()102     public void onFinish() {
103         logd("RemoteOptionsCoordinator: onFinish");
104         mOptionsReqCallback = null;
105         super.onFinish();
106     }
107 
108     @Override
onRequestUpdated(long taskId, int event)109     public void onRequestUpdated(long taskId, int event) {
110         if (mIsFinished) return;
111         RemoteOptionsRequest request = (RemoteOptionsRequest) getUceRequest(taskId);
112         if (request == null) {
113             logw("onRequestUpdated: Cannot find RemoteOptionsRequest taskId=" + taskId);
114             return;
115         }
116 
117         logd("onRequestUpdated: taskId=" + taskId + ", event=" + REQUEST_EVENT_DESC.get(event));
118         switch (event) {
119             case REQUEST_UPDATE_REMOTE_REQUEST_DONE:
120                 handleRemoteRequestDone(request);
121                 break;
122             default:
123                 logw("onRequestUpdated: invalid event " + event);
124                 break;
125         }
126 
127         // End this instance if all the UceRequests in the coordinator are finished.
128         checkAndFinishRequestCoordinator();
129     }
130 
handleRemoteRequestDone(RemoteOptionsRequest request)131     private void handleRemoteRequestDone(RemoteOptionsRequest request) {
132         // Trigger the options request callback
133         RemoteOptResponse response = request.getRemoteOptResponse();
134         RcsContactUceCapability capability = response.getRcsContactCapability();
135         if (capability != null) {
136             boolean isNumberBlocked = response.isNumberBlocked();
137             triggerOptionsReqCallback(capability, isNumberBlocked);
138         } else {
139             int errorCode = response.getErrorSipCode().orElse(SIP_CODE_SERVER_INTERNAL_ERROR);
140             String reason = response.getErrorReason().orElse(SIP_SERVICE_UNAVAILABLE);
141             triggerOptionsReqWithErrorCallback(errorCode, reason);
142         }
143 
144         // Finish this request.
145         request.onFinish();
146 
147         // Remove this request from the activated collection and notify RequestManager.
148         Long taskId = request.getTaskId();
149         RequestResult requestResult = sRemoteResponseCreator.createRequestResult(taskId, response);
150         moveRequestToFinishedCollection(taskId, requestResult);
151     }
152 
triggerOptionsReqCallback(RcsContactUceCapability deviceCaps, boolean isRemoteNumberBlocked)153     private void triggerOptionsReqCallback(RcsContactUceCapability deviceCaps,
154             boolean isRemoteNumberBlocked) {
155         try {
156             logd("triggerOptionsReqCallback: start");
157             mUceStatsWriter.setUceEvent(mSubId, UceStatsWriter.INCOMING_OPTION_EVENT, true, 0,
158                 200);
159 
160             mOptionsReqCallback.respondToCapabilityRequest(deviceCaps, isRemoteNumberBlocked);
161         } catch (RemoteException e) {
162             logw("triggerOptionsReqCallback exception: " + e);
163         } finally {
164             logd("triggerOptionsReqCallback: done");
165         }
166     }
167 
triggerOptionsReqWithErrorCallback(int errorCode, String reason)168     private void triggerOptionsReqWithErrorCallback(int errorCode, String reason) {
169         try {
170             logd("triggerOptionsReqWithErrorCallback: start");
171             mUceStatsWriter.setUceEvent(mSubId, UceStatsWriter.INCOMING_OPTION_EVENT, true, 0,
172                 errorCode);
173 
174             mOptionsReqCallback.respondToCapabilityRequestWithError(errorCode, reason);
175         } catch (RemoteException e) {
176             logw("triggerOptionsReqWithErrorCallback exception: " + e);
177         } finally {
178             logd("triggerOptionsReqWithErrorCallback: done");
179         }
180     }
181 
checkAndFinishRequestCoordinator()182     private void checkAndFinishRequestCoordinator() {
183         synchronized (mCollectionLock) {
184             // Return because there are requests running.
185             if (!mActivatedRequests.isEmpty()) {
186                 return;
187             }
188             // Notify UceRequestManager to remove this instance from the collection.
189             mRequestManagerCallback.notifyRequestCoordinatorFinished(mCoordinatorId);
190             logd("checkAndFinishRequestCoordinator: id=" + mCoordinatorId);
191         }
192     }
193 
194     @VisibleForTesting
getActivatedRequest()195     public Collection<UceRequest> getActivatedRequest() {
196         return mActivatedRequests.values();
197     }
198 
199     @VisibleForTesting
getFinishedRequest()200     public Collection<RequestResult> getFinishedRequest() {
201         return mFinishedRequests.values();
202     }
203 }
204