blob: 2b5e91a9c8a430905e91ea0f99da9f1acbd991ce [file] [log] [blame]
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.ims.rcs.uce.request;
import android.annotation.NonNull;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.RcsContactTerminatedReason;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.aidl.ISubscribeResponseCallback;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.CommandCode;
import com.android.ims.rcs.uce.presence.pidfparser.PidfParser;
import com.android.ims.rcs.uce.presence.pidfparser.PidfParserUtils;
import com.android.ims.rcs.uce.presence.subscribe.SubscribeController;
import com.android.ims.rcs.uce.request.UceRequestManager.RequestManagerCallback;
import com.android.internal.annotations.VisibleForTesting;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* The UceRequest to request the capabilities when the presence mechanism is supported by the
* network.
*/
public class SubscribeRequest extends CapabilityRequest {
// The result callback of the capabilities request from IMS service.
private final ISubscribeResponseCallback mResponseCallback =
new ISubscribeResponseCallback.Stub() {
@Override
public void onCommandError(int code) {
SubscribeRequest.this.onCommandError(code);
}
@Override
public void onNetworkResponse(int code, String reason) {
SubscribeRequest.this.onNetworkResponse(code, reason);
}
@Override
public void onNetworkRespHeader(int code, String reasonPhrase,
int reasonHeaderCause, String reasonHeaderText) {
SubscribeRequest.this.onNetworkResponse(code, reasonPhrase, reasonHeaderCause,
reasonHeaderText);
}
@Override
public void onNotifyCapabilitiesUpdate(List<String> pidfXmls) {
SubscribeRequest.this.onCapabilitiesUpdate(pidfXmls);
}
@Override
public void onResourceTerminated(List<RcsContactTerminatedReason> terminatedList) {
SubscribeRequest.this.onResourceTerminated(terminatedList);
}
@Override
public void onTerminated(String reason, long retryAfterMillis) {
SubscribeRequest.this.onTerminated(reason, retryAfterMillis);
}
};
private SubscribeController mSubscribeController;
public SubscribeRequest(int subId, @UceRequestType int requestType,
RequestManagerCallback taskMgrCallback, SubscribeController subscribeController) {
super(subId, requestType, taskMgrCallback);
mSubscribeController = subscribeController;
logd("SubscribeRequest created");
}
@VisibleForTesting
public SubscribeRequest(int subId, @UceRequestType int requestType,
RequestManagerCallback taskMgrCallback, SubscribeController subscribeController,
CapabilityRequestResponse requestResponse) {
super(subId, requestType, taskMgrCallback, requestResponse);
mSubscribeController = subscribeController;
}
@Override
public void onFinish() {
mSubscribeController = null;
super.onFinish();
logd("SubscribeRequest finish");
}
@Override
public void requestCapabilities(@NonNull List<Uri> requestCapUris) {
SubscribeController subscribeController = mSubscribeController;
if (subscribeController == null) {
logw("requestCapabilities: request is finished");
mRequestResponse.setRequestInternalError(RcsUceAdapter.ERROR_GENERIC_FAILURE);
mRequestManagerCallback.notifyRequestError(mCoordinatorId, mTaskId);
return;
}
logi("requestCapabilities: size=" + requestCapUris.size());
try {
// Send the capabilities request.
subscribeController.requestCapabilities(requestCapUris, mResponseCallback);
// Setup the timeout timer.
setupRequestTimeoutTimer();
} catch (RemoteException e) {
logw("requestCapabilities exception: " + e);
mRequestResponse.setRequestInternalError(RcsUceAdapter.ERROR_GENERIC_FAILURE);
mRequestManagerCallback.notifyRequestError(mCoordinatorId, mTaskId);
}
}
// Receive the command error callback which is triggered by ISubscribeResponseCallback.
private void onCommandError(@CommandCode int cmdError) {
logd("onCommandError: error code=" + cmdError);
if (mIsFinished) {
logw("onCommandError: request is already finished");
return;
}
mRequestResponse.setCommandError(cmdError);
mRequestManagerCallback.notifyCommandError(mCoordinatorId, mTaskId);
}
// Receive the network response callback which is triggered by ISubscribeResponseCallback.
private void onNetworkResponse(int sipCode, String reason) {
logd("onNetworkResponse: code=" + sipCode + ", reason=" + reason);
if (mIsFinished) {
logw("onNetworkResponse: request is already finished");
return;
}
mRequestResponse.setNetworkResponseCode(sipCode, reason);
mRequestManagerCallback.notifyNetworkResponse(mCoordinatorId, mTaskId);
}
// Receive the network response callback which is triggered by ISubscribeResponseCallback.
private void onNetworkResponse(int sipCode, String reasonPhrase,
int reasonHeaderCause, String reasonHeaderText) {
logd("onNetworkResponse: code=" + sipCode + ", reasonPhrase=" + reasonPhrase +
", reasonHeaderCause=" + reasonHeaderCause +
", reasonHeaderText=" + reasonHeaderText);
if (mIsFinished) {
logw("onNetworkResponse: request is already finished");
return;
}
mRequestResponse.setNetworkResponseCode(sipCode, reasonPhrase, reasonHeaderCause,
reasonHeaderText);
mRequestManagerCallback.notifyNetworkResponse(mCoordinatorId, mTaskId);
}
// Receive the resource terminated callback which is triggered by ISubscribeResponseCallback.
private void onResourceTerminated(List<RcsContactTerminatedReason> terminatedResource) {
if (mIsFinished) {
logw("onResourceTerminated: request is already finished");
return;
}
if (terminatedResource == null) {
logw("onResourceTerminated: the parameter is null");
terminatedResource = Collections.emptyList();
}
logd("onResourceTerminated: size=" + terminatedResource.size());
// Add the terminated resource into the RequestResponse and notify the RequestManager
// to process the RcsContactUceCapabilities update.
mRequestResponse.addTerminatedResource(terminatedResource);
mRequestManagerCallback.notifyResourceTerminated(mCoordinatorId, mTaskId);
}
// Receive the capabilities update callback which is triggered by ISubscribeResponseCallback.
private void onCapabilitiesUpdate(List<String> pidfXml) {
if (mIsFinished) {
logw("onCapabilitiesUpdate: request is already finished");
return;
}
if (pidfXml == null) {
logw("onCapabilitiesUpdate: The parameter is null");
pidfXml = Collections.EMPTY_LIST;
}
// Convert from the pidf xml to the list of RcsContactUceCapability
List<RcsContactUceCapability> capabilityList = pidfXml.stream()
.map(pidf -> PidfParser.getRcsContactUceCapability(pidf))
.filter(Objects::nonNull)
.collect(Collectors.toList());
// When the given PIDF xml is empty, set the contacts who have not received the
// capabilities updated as non-RCS user.
if (capabilityList.isEmpty()) {
logd("onCapabilitiesUpdate: The capabilities list is empty, Set to non-RCS user.");
List<Uri> notReceiveCapUpdatedContactList =
mRequestResponse.getNotReceiveCapabilityUpdatedContact();
capabilityList = notReceiveCapUpdatedContactList.stream()
.map(PidfParserUtils::getNotFoundContactCapabilities)
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
logd("onCapabilitiesUpdate: PIDF size=" + pidfXml.size()
+ ", contact capability size=" + capabilityList.size());
// Add these updated RcsContactUceCapability into the RequestResponse and notify
// the RequestManager to process the RcsContactUceCapabilities updated.
mRequestResponse.addUpdatedCapabilities(capabilityList);
mRequestManagerCallback.notifyCapabilitiesUpdated(mCoordinatorId, mTaskId);
}
// Receive the terminated callback which is triggered by ISubscribeResponseCallback.
private void onTerminated(String reason, long retryAfterMillis) {
logd("onTerminated: reason=" + reason + ", retryAfter=" + retryAfterMillis);
if (mIsFinished) {
logd("onTerminated: This request is already finished");
return;
}
mRequestResponse.setTerminated(reason, retryAfterMillis);
mRequestManagerCallback.notifyTerminated(mCoordinatorId, mTaskId);
}
@VisibleForTesting
public ISubscribeResponseCallback getResponseCallback() {
return mResponseCallback;
}
}